aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/memory/qv4writebarrier_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/memory/qv4writebarrier_p.h')
-rw-r--r--src/qml/memory/qv4writebarrier_p.h100
1 files changed, 88 insertions, 12 deletions
diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h
index c0f508f962..838ed7a456 100644
--- a/src/qml/memory/qv4writebarrier_p.h
+++ b/src/qml/memory/qv4writebarrier_p.h
@@ -55,6 +55,11 @@
QT_BEGIN_NAMESPACE
+#define WRITEBARRIER_steele -1
+#define WRITEBARRIER_none 1
+
+#define WRITEBARRIER(x) (1/WRITEBARRIER_##x == 1)
+
namespace QV4 {
namespace WriteBarrier {
@@ -64,20 +69,79 @@ enum Type {
Barrier
};
-inline void write(QV4::ExecutionEngine *engine, QV4::Heap::Base *base, QV4::Value *slot, QV4::Value value)
+enum NewValueType {
+ Primitive,
+ Object,
+ Unknown
+};
+
+// ### this needs to be filled with a real memory fence once marking is concurrent
+Q_ALWAYS_INLINE void fence() {}
+
+#if WRITEBARRIER(steele)
+
+template <NewValueType type>
+static Q_CONSTEXPR inline bool isRequired() {
+ return type != Primitive;
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Value *slot, Value value)
+{
+ *slot = value;
+ if (engine->writeBarrierActive && isRequired<Unknown>()) {
+ fence();
+ base->setGrayBit();
+ }
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Value *slot, Heap::Base *value)
+{
+ *slot = value;
+ if (engine->writeBarrierActive && isRequired<Object>()) {
+ fence();
+ base->setGrayBit();
+ }
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Heap::Base **slot, Heap::Base *value)
+{
+ *slot = value;
+ if (engine->writeBarrierActive) {
+ fence();
+ base->setGrayBit();
+ }
+}
+
+#elif WRITEBARRIER(none)
+
+template <NewValueType type>
+static Q_CONSTEXPR inline bool isRequired() {
+ return false;
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Value *slot, Value value)
+{
+ Q_UNUSED(engine);
+ Q_UNUSED(base);
+ *slot = value;
+}
+
+inline void write(EngineBase *engine, Heap::Base *base, Value *slot, Heap::Base *value)
{
Q_UNUSED(engine);
Q_UNUSED(base);
*slot = value;
}
-inline void write(QV4::ExecutionEngine *engine, QV4::Heap::Base *base, QV4::Heap::Base **slot, QV4::Heap::Base *value)
+inline void write(EngineBase *engine, Heap::Base *base, Heap::Base **slot, Heap::Base *value)
{
Q_UNUSED(engine);
Q_UNUSED(base);
*slot = value;
}
+#endif
+
}
namespace Heap {
@@ -88,9 +152,14 @@ struct Pointer {
T operator->() const { return ptr; }
operator T () const { return ptr; }
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
void set(ExecutionEngine *e, T newVal) {
- Q_UNUSED(e);
- ptr = newVal;
+ WriteBarrier::write(e, base(), reinterpret_cast<Heap::Base **>(&ptr), reinterpret_cast<Heap::Base *>(newVal));
}
template <typename Type>
@@ -106,9 +175,14 @@ V4_ASSERT_IS_TRIVIAL(V4PointerCheck)
template <size_t offset>
struct HeapValue : Value {
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
void set(ExecutionEngine *e, const Value &newVal) {
- Q_UNUSED(e);
- setRawValue(newVal.rawValue());
+ WriteBarrier::write(e, base(), this, newVal);
}
};
@@ -118,15 +192,17 @@ struct ValueArray {
uint alloc;
Value values[1];
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
void set(ExecutionEngine *e, uint index, Value v) {
- Q_UNUSED(e);
- Q_ASSERT(index < alloc);
- values[index] = v;
+ WriteBarrier::write(e, base(), values + index, v);
}
void set(ExecutionEngine *e, uint index, Heap::Base *b) {
- Q_UNUSED(e);
- Q_ASSERT(index < alloc);
- values[index] = b;
+ WriteBarrier::write(e, base(), values + index, b);
}
inline const Value &operator[] (uint index) const {
Q_ASSERT(index < alloc);