From 002fdc48d43e4fd67921e0cd46c28d28aee06848 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 Nov 2017 16:02:10 +0100 Subject: 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 --- src/qml/jsruntime/qv4argumentsobject_p.h | 6 +-- src/qml/jsruntime/qv4arraydata.cpp | 3 +- src/qml/jsruntime/qv4arraydata_p.h | 2 +- src/qml/jsruntime/qv4context_p.h | 6 +-- src/qml/jsruntime/qv4dataview_p.h | 2 +- src/qml/jsruntime/qv4engine_p.h | 29 ------------- src/qml/jsruntime/qv4errorobject_p.h | 2 +- src/qml/jsruntime/qv4functionobject.cpp | 2 - src/qml/jsruntime/qv4functionobject_p.h | 4 +- src/qml/jsruntime/qv4managed.cpp | 1 - src/qml/jsruntime/qv4managed_p.h | 12 +++--- src/qml/jsruntime/qv4memberdata_p.h | 2 +- src/qml/jsruntime/qv4object.cpp | 13 +++++- src/qml/jsruntime/qv4object_p.h | 13 +++--- src/qml/jsruntime/qv4objectiterator.cpp | 4 +- src/qml/jsruntime/qv4objectiterator_p.h | 4 +- src/qml/jsruntime/qv4qmlcontext_p.h | 2 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 6 +-- src/qml/jsruntime/qv4qobjectwrapper_p.h | 4 +- src/qml/jsruntime/qv4regexpobject_p.h | 4 +- src/qml/jsruntime/qv4string.cpp | 9 ++-- src/qml/jsruntime/qv4string_p.h | 2 +- src/qml/jsruntime/qv4stringobject_p.h | 2 +- src/qml/jsruntime/qv4typedarray_p.h | 2 +- src/qml/jsruntime/qv4value_p.h | 7 +++ src/qml/memory/qv4heap_p.h | 23 ++++++++-- src/qml/memory/qv4mm.cpp | 58 ------------------------- src/qml/memory/qv4mmdefs_p.h | 61 ++++++++++++--------------- src/qml/memory/qv4writebarrier_p.h | 36 +++++++++++++--- src/qml/qml/qqmlcomponent.cpp | 2 +- src/qml/qml/qqmlxmlhttprequest.cpp | 2 +- src/quick/items/context2d/qquickcontext2d.cpp | 9 ++-- src/quick/items/qquickitem.cpp | 8 ++-- 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(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::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(b); + Heap::Object::markObjects(base, stack); +} + +void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack) +{ + Object *o = static_cast(b); + if (o->memberData) + o->memberData->mark(stack); + if (o->arrayData) + o->arrayData->mark(stack); uint nInline = o->vtable()->nInlineProperties; Value *v = reinterpret_cast(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(that); + ForEachIteratorObject *o = static_cast(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(&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(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(that); + QObjectWrapper *This = static_cast(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 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(that); + String *s = static_cast(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(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 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(this); - while (m) { - MarkFlags mark = static_cast(m & 3); - switch (mark) { - case Mark_NoMark: - break; - case Mark_Value: -// qDebug() << "marking value at " << mem; - reinterpret_cast(mem)->mark(markStack); - break; - case Mark_Pointer: { -// qDebug() << "marking pointer at " << mem; - Heap::Base *p = *reinterpret_cast(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(h)); - ValueArray<0> *a = reinterpret_cast *>(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 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 -struct MarkFlagEvaluator { - static Q_CONSTEXPR quint64 value = 0; -}; -template -struct MarkFlagEvaluator> { - static Q_CONSTEXPR quint64 value = static_cast(Mark_Pointer) << (2*o / sizeof(quintptr)); -}; -template -struct MarkFlagEvaluator> { - static Q_CONSTEXPR quint64 value = static_cast(Mark_ValueArray) << (2*o / sizeof(quintptr)); -}; -template -struct MarkFlagEvaluator> { - static Q_CONSTEXPR quint64 value = static_cast(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> { #define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \ type name; -#define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \ - MarkFlagEvaluator::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(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 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(this) - (offset/sizeof(Heap::Base)); @@ -124,16 +124,18 @@ struct Pointer { } void set(EngineBase *e, T newVal) { - WriteBarrier::write(e, base(), reinterpret_cast(&ptr), reinterpret_cast(newVal)); + WriteBarrier::write(e, base(), &ptr, reinterpret_cast(newVal)); } - T get() { return ptr; } + T get() const { return reinterpret_cast(ptr); } template Type *cast() { return static_cast(ptr); } + Heap::Base *heapObject() const { return ptr; } + private: - T ptr; + Heap::Base *ptr; }; typedef Pointer 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, 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(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(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(that); + QObjectWrapper *This = static_cast(that); if (QQuickItem *item = static_cast(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) -- cgit v1.2.3