diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-01-04 10:20:34 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-01-19 10:13:58 +0000 |
commit | e1b166dd304ed3bed2d5ecb1404f253eddbf2d06 (patch) | |
tree | a39142a8d11e97a8241d3e3dc2ac264f9ecd79dc | |
parent | 1fe206712755b0d99f91bc7897f0a705ec583f2d (diff) |
Disentangle include dependencies around the write barrier
The write barrier header should have minimal dependencies.
Change-Id: I071718c2fafe5020d1093ca3b363844f7a9b7b35
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4memberdata_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 89 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 4 | ||||
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 34 | ||||
-rw-r--r-- | src/qml/memory/qv4writebarrier_p.h | 131 |
6 files changed, 130 insertions, 134 deletions
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index 7345790ac3..12eaf336b9 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -79,7 +79,7 @@ struct MemberData : Managed Value *slot; void set(EngineBase *e, Value newVal) { - WriteBarrier::write(e, base, slot, newVal); + WriteBarrier::write(e, base, slot->data_ptr(), newVal.asReturnedValue()); } const Value *operator->() const { return slot; } const Value &operator*() const { return *slot; } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 0ce9406a01..308583d46c 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -85,12 +85,12 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) { void setInlineProperty(ExecutionEngine *e, uint index, Value v) { Q_ASSERT(index < vtable()->nInlineProperties); Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index; - WriteBarrier::write(e, this, prop, v); + WriteBarrier::write(e, this, prop->data_ptr(), v.asReturnedValue()); } void setInlineProperty(ExecutionEngine *e, uint index, Heap::Base *b) { Q_ASSERT(index < vtable()->nInlineProperties); Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index; - WriteBarrier::write(e, this, prop, b); + WriteBarrier::write(e, this, prop->data_ptr(), b->asReturnedValue()); } QV4::MemberData::Index writablePropertyData(uint index) { diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index a0495cca61..843fbc1d91 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -457,6 +457,7 @@ public: uint asArrayLength(bool *ok) const; #endif + ReturnedValue *data_ptr() { return &_val; } ReturnedValue asReturnedValue() const { return _val; } static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; } @@ -792,6 +793,94 @@ inline double Value::toInteger() const } +template <size_t o> +struct HeapValue : Value { + static Q_CONSTEXPR size_t offset = o; + Heap::Base *base() { + Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base)); + Q_ASSERT(base->inUse()); + return base; + } + + void set(EngineBase *e, const Value &newVal) { + WriteBarrier::write(e, base(), data_ptr(), newVal.asReturnedValue()); + } + void set(EngineBase *e, Heap::Base *b) { + WriteBarrier::write(e, base(), data_ptr(), b->asReturnedValue()); + } +}; + +template <size_t o> +struct ValueArray { + static Q_CONSTEXPR size_t offset = o; + uint size; + 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(EngineBase *e, uint index, Value v) { + WriteBarrier::write(e, base(), values[index].data_ptr(), v.asReturnedValue()); + } + void set(EngineBase *e, uint index, Heap::Base *b) { + WriteBarrier::write(e, base(), values[index].data_ptr(), b->asReturnedValue()); + } + inline const Value &operator[] (uint index) const { + Q_ASSERT(index < alloc); + return values[index]; + } + inline const Value *data() const { + return values; + } + + void insertData(EngineBase *e, uint index, Value v) { + for (uint i = size - 1; i > index; --i) { + values[i] = values[i - 1]; + } + set(e, index, v); + } + void removeData(EngineBase *e, uint index, int n = 1) { + Q_UNUSED(e); + for (uint i = index; i < size - n; ++i) { + 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 +// constant across all architecture, otherwise JIT cross-compiled code will +// have wrong offsets between host and target. +Q_STATIC_ASSERT(offsetof(ValueArray<0>, values) == 8); + + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index c761846e67..8355fbca71 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -634,7 +634,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, MOTH_BEGIN_INSTR(StoreLocal) CHECK_EXCEPTION; auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m()); - QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, ACC); + QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc); MOTH_END_INSTR(StoreLocal) MOTH_BEGIN_INSTR(LoadScopedLocal) @@ -645,7 +645,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, MOTH_BEGIN_INSTR(StoreScopedLocal) CHECK_EXCEPTION; auto cc = getScope(stack, scope); - QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, ACC); + QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc); MOTH_END_INSTR(StoreScopedLocal) MOTH_BEGIN_INSTR(LoadRuntimeString) diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index 7bc841b21d..53933cd090 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -53,6 +53,7 @@ #include <QtCore/QString> #include <private/qv4global_p.h> #include <private/qv4mmdefs_p.h> +#include <private/qv4writebarrier_p.h> #include <private/qv4internalclass_p.h> #include <QSharedPointer> @@ -195,6 +196,39 @@ void Heap::Base::mark(QV4::MarkStack *markStack) } } +namespace Heap { + +template <typename T, size_t o> +struct Pointer { + static Q_CONSTEXPR size_t offset = o; + 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)); + Q_ASSERT(base->inUse()); + return base; + } + + void set(EngineBase *e, T newVal) { + WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal)); + } + + 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: + Heap::Base *ptr; +}; +typedef Pointer<char *, 0> V4PointerCheck; +Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value); + +} + #ifdef QT_NO_QOBJECT template <class T> struct QQmlQPointer { diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h index 39413a6f09..8b04aa6cb1 100644 --- a/src/qml/memory/qv4writebarrier_p.h +++ b/src/qml/memory/qv4writebarrier_p.h @@ -51,7 +51,7 @@ // #include <private/qv4global_p.h> -#include <private/qv4value_p.h> +#include <private/qv4enginebase_p.h> QT_BEGIN_NAMESPACE @@ -84,14 +84,7 @@ 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) +inline void write(EngineBase *engine, Heap::Base *base, ReturnedValue *slot, ReturnedValue value) { Q_UNUSED(engine); Q_UNUSED(base); @@ -109,126 +102,6 @@ inline void write(EngineBase *engine, Heap::Base *base, Heap::Base **slot, Heap: } -namespace Heap { - -template <typename T, size_t o> -struct Pointer { - static Q_CONSTEXPR size_t offset = o; - 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)); - Q_ASSERT(base->inUse()); - return base; - } - - void set(EngineBase *e, T newVal) { - WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal)); - } - - 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: - Heap::Base *ptr; -}; -typedef Pointer<char *, 0> V4PointerCheck; -Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value); - -} - -template <size_t o> -struct HeapValue : Value { - static Q_CONSTEXPR size_t offset = o; - Heap::Base *base() { - Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base)); - Q_ASSERT(base->inUse()); - return base; - } - - void set(EngineBase *e, const Value &newVal) { - WriteBarrier::write(e, base(), this, newVal); - } - void set(EngineBase *e, Heap::Base *b) { - WriteBarrier::write(e, base(), this, b); - } -}; - -template <size_t o> -struct ValueArray { - static Q_CONSTEXPR size_t offset = o; - uint size; - 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(EngineBase *e, uint index, Value v) { - WriteBarrier::write(e, base(), values + index, v); - } - void set(EngineBase *e, uint index, Heap::Base *b) { - WriteBarrier::write(e, base(), values + index, b); - } - inline const Value &operator[] (uint index) const { - Q_ASSERT(index < alloc); - return values[index]; - } - inline const Value *data() const { - return values; - } - - void insertData(EngineBase *e, uint index, Value v) { - for (uint i = size - 1; i > index; --i) { - values[i] = values[i - 1]; - } - set(e, index, v); - } - void removeData(EngineBase *e, uint index, int n = 1) { - Q_UNUSED(e); - for (uint i = index; i < size - n; ++i) { - 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 -// constant across all architecture, otherwise JIT cross-compiled code will -// have wrong offsets between host and target. -Q_STATIC_ASSERT(offsetof(ValueArray<0>, values) == 8); - } QT_END_NAMESPACE |