diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-01-31 13:25:09 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-03-09 08:58:31 +0000 |
commit | 518e258d59adc976e2e8aa9a7f9ef36d8b8cdb66 (patch) | |
tree | 33b90cb45ebfa4cb6767db85caaafcf6ac83d404 /src/qml | |
parent | 8b3cbc4403e3eac286613691c11aa1ded588da59 (diff) |
Make every member of a Heap object aware of its offset inside the object
This will allow adding a write barrier to those fields with manageable
effort.
Change-Id: I7d06d7ffccbcefe66e2524c64c962353c91c2766
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 5 | ||||
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 4 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 2 | ||||
-rw-r--r-- | src/qml/memory/qv4mmdefs_p.h | 48 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 4 |
10 files changed, 58 insertions, 14 deletions
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index ccea1dbc80..f544821729 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -171,7 +171,7 @@ V4_ASSERT_IS_TRIVIAL(GlobalContext) #define CatchContextMembers(class, Member) \ Member(class, Pointer, String *, exceptionVarName) \ - Member(class, Value, Value, exceptionValue) + Member(class, HeapValue, HeapValue, exceptionValue) DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) { DECLARE_MARK_TABLE(CatchContext); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 1fc40e6ff6..c7dac7d3e5 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -123,7 +123,7 @@ struct ScriptFunction : FunctionObject { #define BoundFunctionMembers(class, Member) \ Member(class, Pointer, FunctionObject *, target) \ - Member(class, Value, Value, boundThis) \ + Member(class, HeapValue, HeapValue, boundThis) \ Member(class, Pointer, MemberData *, boundArgs) DECLARE_HEAP_OBJECT(BoundFunction, FunctionObject) { diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index ea3e1d750e..cd8fb91f7a 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -199,6 +199,7 @@ struct ScriptFunction; struct InternalClass; struct Property; struct Value; +template<size_t> struct HeapValue; template<size_t> struct ValueArray; struct Lookup; struct ArrayData; diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 5b43710c03..63b132c2e6 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -82,6 +82,8 @@ DECLARE_HEAP_OBJECT(Object, Base) { Value *propertyData(uint index) { return memberData->values.v + index; } }; +Q_STATIC_ASSERT(Object::markTable == ((2 << 4) | (2 << 6) | (2 << 8))); + } #define V4_OBJECT(superClass) \ diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index b429524b71..c2eeb32b88 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -86,7 +86,7 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) { }; #define RegExpCtorMembers(class, Member) \ - Member(class, Value, Value, lastMatch) \ + Member(class, HeapValue, HeapValue, lastMatch) \ Member(class, Pointer, String *, lastInput) \ Member(class, NoMark, int, lastMatchStart) \ Member(class, NoMark, int, lastMatchEnd) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 771d28dce8..3d7776b736 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -709,6 +709,11 @@ inline unsigned int Value::toUInt32() const } template <size_t offset> +struct HeapValue : Value { + HeapValue &operator = (const Value &other) { setRawValue(other.rawValue()); return *this; } +}; + +template <size_t offset> struct ValueArray { uint size; uint alloc; diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index febe4e6446..b3dfa407f8 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -164,8 +164,10 @@ struct Q_QML_EXPORT Base { }; V4_ASSERT_IS_TRIVIAL(Base) -template <typename T, size_t> +template <typename T, size_t o> struct Pointer { + static Q_CONSTEXPR size_t offset = o; + static Q_CONSTEXPR quint64 markBits = Mark_Pointer << (o >> 2); T operator->() const { return ptr; } operator T () const { return ptr; } diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 89cf9caf9e..edd26cf982 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -762,7 +762,7 @@ void MemoryManager::drainMarkStack(Value *markBase) break; case Mark_Pointer: { // qDebug() << "marking pointer at " << mem; - Heap::Base *p = reinterpret_cast<Heap::Base *>(mem); + Heap::Base *p = *reinterpret_cast<Heap::Base **>(mem); if (p) p->mark(engine); break; diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h index e4d5ce9da2..63e51f9742 100644 --- a/src/qml/memory/qv4mmdefs_p.h +++ b/src/qml/memory/qv4mmdefs_p.h @@ -265,24 +265,58 @@ enum MarkFlags { 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)); +}; + +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION(c, gcType, type, name) \ + HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_##gcType(c, type, name) + +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_Pointer(c, type, name) Pointer<type, 0> name; +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_NoMark(c, type, name) type name; +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_HeapValue(c, type, name) HeapValue<0> name; +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_ValueArray(c, type, name) ValueArray<0> name; + #define HEAP_OBJECT_MEMBER_EXPANSION(c, gcType, type, name) \ HEAP_OBJECT_MEMBER_EXPANSION_##gcType(c, type, name) -#define HEAP_OBJECT_MEMBER_EXPANSION_Pointer(c, type, name) Pointer<type, 0> name; -#define HEAP_OBJECT_MEMBER_EXPANSION_NoMark(c, type, name) type name; -#define HEAP_OBJECT_MEMBER_EXPANSION_Value(c, type, name) type name; -#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) ValueArray<0> name; +#define HEAP_OBJECT_MEMBER_EXPANSION_Pointer(c, type, name) \ + Pointer<type, offsetof(c##OffsetStruct, name) + baseOffset> name; +#define HEAP_OBJECT_MEMBER_EXPANSION_NoMark(c, type, name) \ + type name; +#define HEAP_OBJECT_MEMBER_EXPANSION_HeapValue(c, type, name) \ + HeapValue<offsetof(c##OffsetStruct, name) + baseOffset> name; +#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \ + ValueArray<offsetof(c##OffsetStruct, name) + baseOffset> name; #define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \ - (Mark_##gcType << (offsetof(class, name) >> 2)) | + MarkFlagEvaluator<decltype(class::name)>::value | #define DECLARE_HEAP_OBJECT(name, base) \ +struct name##OffsetStruct { \ + name##Members(name, HEAP_OBJECT_OFFSET_MEMBER_EXPANSION) \ +}; \ +struct name##SizeStruct : base, name##OffsetStruct {}; \ struct name##Data { \ + static Q_CONSTEXPR size_t baseOffset = sizeof(name##SizeStruct) - sizeof(name##OffsetStruct); \ name##Members(name, HEAP_OBJECT_MEMBER_EXPANSION) \ }; \ -struct name##SizeStruct : base, name##Data {}; \ +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) << (((sizeof(name##SizeStruct) - sizeof(name##Data)) >> 2) | QV4::Heap::base::markTable; \ + (name##Members(name##Data, HEAP_OBJECT_MARK_EXPANSION) 0) | QV4::Heap::base::markTable; \ \ struct name : base, name##Data diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 79e52f3914..c1a0637d00 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1047,8 +1047,8 @@ namespace QV4 { namespace Heap { #define QmlIncubatorObjectMembers(class, Member) \ - Member(class, Value, Value, valuemap) \ - Member(class, Value, Value, statusChanged) \ + Member(class, HeapValue, HeapValue, valuemap) \ + Member(class, HeapValue, HeapValue, statusChanged) \ Member(class, Pointer, QmlContext *, qmlContext) \ Member(class, NoMark, QQmlComponentIncubator *, incubator) \ Member(class, NoMark, QQmlQPointer<QObject>, parent) |