aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2024-02-20 16:03:35 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2024-03-05 14:06:28 +0100
commit205d1474c365965c125101457f8ad89889f53f3a (patch)
treed8ba6c6a7b9c25252931340d1f170214355b8d5d /src/qml
parentb60b1e17a2d0dc6f263dc0c788f0a6bf14e6d0de (diff)
WriteBarrier: Introduce Pointer and HeapObjectWrapper abstractions
We already have QV4::Pointer as a way to keep references to heap items which need to be protected by the WriteBarrier. However, it is only meant to be used in other HeapItems. WriteBarrier::Pointer is its complement which can be used in the few classes which live on the C++ heap and store references to HeapItems. In the same vein, introduce HeapObjectWrapper, which has the same purpose but is trivial (so that it can be used in classes that are required to be trivial). Change-Id: I4193fa4ae4fe7c997ff5769168ac15d60bf3726d Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/memory/qv4writebarrier_p.h65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h
index 9b26766ee5..ddee183982 100644
--- a/src/qml/memory/qv4writebarrier_p.h
+++ b/src/qml/memory/qv4writebarrier_p.h
@@ -54,6 +54,71 @@ struct WriteBarrier {
if (engine->isGCOngoing)
(std::forward<F>(markFunction))(engine->memoryManager->markStack());
}
+
+ // HeapObjectWrapper(Base) are helper classes to ensure that
+ // we always use a WriteBarrier when setting heap-objects
+ // they are also trivial; if triviality is not required, use Pointer instead
+ struct HeapObjectWrapperBase
+ {
+ // enum class avoids accidental construction via brace-init
+ enum class PointerWrapper : quintptr {};
+ PointerWrapper wrapped;
+
+ void clear() { wrapped = PointerWrapper(quintptr(0)); }
+ };
+
+ template<typename HeapType>
+ struct HeapObjectWrapperCommon : HeapObjectWrapperBase
+ {
+ HeapType *get() const { return reinterpret_cast<HeapType *>(wrapped); }
+ operator HeapType *() const { return get(); }
+ HeapType * operator->() const { return get(); }
+
+ template <typename ConvertibleToHeapType>
+ void set(QV4::EngineBase *engine, ConvertibleToHeapType *heapObject)
+ {
+ WriteBarrier::markCustom(engine, [heapObject](QV4::MarkStack *ms){
+ if (heapObject)
+ heapObject->mark(ms);
+ });
+ wrapped = static_cast<HeapObjectWrapperBase::PointerWrapper>(quintptr(heapObject));
+ }
+ };
+
+ // all types are trivial; we however want to block copies bypassing the write barrier
+ // therefore, all members use a PhantomTag to reduce the likelihood
+ template<typename HeapType, int PhantomTag>
+ struct HeapObjectWrapper : HeapObjectWrapperCommon<HeapType> {};
+
+ /* similar Heap::Pointer, but without the Base conversion (and its inUse assert)
+ and for storing references in engine classes stored on the native heap
+ Stores a "non-owning" reference to a heap-item (in the C++ sense), but should
+ generally mark the heap-item; therefore set goes through a write-barrier
+ */
+ template<typename T>
+ struct Pointer
+ {
+ Pointer() = default;
+ ~Pointer() = default;
+ Q_DISABLE_COPY_MOVE(Pointer)
+ T* operator->() const { return get(); }
+ operator T* () const { return get(); }
+
+ void set(EngineBase *e, T *newVal) {
+ WriteBarrier::markCustom(e, [newVal](QV4::MarkStack *ms) {
+ if (newVal)
+ newVal->mark(ms);
+ });
+ ptr = newVal;
+ }
+
+ T* get() const { return ptr; }
+
+
+
+ private:
+ T *ptr = nullptr;
+ };
};
// ### this needs to be filled with a real memory fence once marking is concurrent