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 <erik.verbruggen@qt.io>
This commit is contained in:
Lars Knoll 2017-11-02 16:02:10 +01:00
parent 010197a421
commit 002fdc48d4
33 changed files with 151 additions and 191 deletions

View File

@ -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,

View File

@ -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
};

View File

@ -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 };

View File

@ -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);
};

View File

@ -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(); }
};

View File

@ -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<const HeapItem *>(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);

View File

@ -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,

View File

@ -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))
{

View File

@ -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);
};

View File

@ -49,7 +49,6 @@ const VTable Managed::static_vtbl =
0,
0,
0,
0,
Managed::IsExecutionContext,
Managed::IsString,
Managed::IsObject,

View File

@ -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<classname, Object>::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 {

View File

@ -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)

View File

@ -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<Heap::Object *>(b);
Heap::Object::markObjects(base, stack);
}
void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
{
Object *o = static_cast<Object *>(b);
if (o->memberData)
o->memberData->mark(stack);
if (o->arrayData)
o->arrayData->mark(stack);
uint nInline = o->vtable()->nInlineProperties;
Value *v = reinterpret_cast<Value *>(o) + o->vtable()->inlinePropertyOffset;
const Value *end = v + nInline;

View File

@ -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;

View File

@ -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<ForEachIteratorObject::Data *>(that);
ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
o->workArea[0].mark(markStack);
o->workArea[1].mark(markStack);
Object::markObjects(that, markStack);

View File

@ -116,6 +116,7 @@ struct ForEachIteratorObject : Object {
ObjectIterator &it() { return *reinterpret_cast<ObjectIterator*>(&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

View File

@ -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<QQmlContextWrapper *>(activation.get()); }
void init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml);

View File

@ -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<QObjectWrapper::Data *>(that);
QObjectWrapper *This = static_cast<QObjectWrapper *>(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)

View File

@ -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<QObject> 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);

View File

@ -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();

View File

@ -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<String::Data *>(that);
String *s = static_cast<String *>(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)

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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();

View File

@ -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<const HeapItem *>(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 <class T>
struct QQmlQPointer {

View File

@ -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<void **>(this);
while (m) {
MarkFlags mark = static_cast<MarkFlags>(m & 3);
switch (mark) {
case Mark_NoMark:
break;
case Mark_Value:
// qDebug() << "marking value at " << mem;
reinterpret_cast<Value *>(mem)->mark(markStack);
break;
case Mark_Pointer: {
// qDebug() << "marking pointer at " << mem;
Heap::Base *p = *reinterpret_cast<Heap::Base **>(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<void **>(h));
ValueArray<0> *a = reinterpret_cast<ValueArray<0> *>(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<const char*, int> MMStatsHash;
Q_GLOBAL_STATIC(MMStatsHash, freedObjectStatsGlobal)

View File

@ -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 <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));
};
// 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<HeapValue<o>> {
#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \
type<offsetof(c##OffsetStruct, name) + baseOffset> name;
#define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \
MarkFlagEvaluator<decltype(class::name)>::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<class *>(b); \
class##Data::SuperClass::markObjects(o, stack); \
class##Members(class, HEAP_OBJECT_MARKOBJECTS_EXPANSION) \
}
}

View File

@ -114,8 +114,8 @@ namespace Heap {
template <typename T, size_t o>
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<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
@ -124,16 +124,18 @@ struct Pointer {
}
void set(EngineBase *e, T newVal) {
WriteBarrier::write(e, base(), reinterpret_cast<Heap::Base **>(&ptr), reinterpret_cast<Heap::Base *>(newVal));
WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal));
}
T get() { return ptr; }
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:
T ptr;
Heap::Base *ptr;
};
typedef Pointer<char *, 0> 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

View File

@ -1098,7 +1098,7 @@ namespace Heap {
Member(class, NoMark, QQmlQPointer<QObject>, parent)
DECLARE_HEAP_OBJECT(QmlIncubatorObject, Object) {
DECLARE_MARK_TABLE(QmlIncubatorObject);
DECLARE_MARKOBJECTS(QmlIncubatorObject);
void init(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
inline void destroy();

View File

@ -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);
};

View File

@ -529,6 +529,11 @@ struct QQuickJSContext2DPixelData : Object {
struct QQuickJSContext2DImageData : Object {
void init();
static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) {
static_cast<QQuickJSContext2DImageData *>(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<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(markStack);
QV4::Object::markObjects(that, markStack);
}
};
void QV4::Heap::QQuickJSContext2DImageData::init()

View File

@ -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<QObjectWrapper::Data *>(that);
QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
if (QQuickItem *item = static_cast<QQuickItem*>(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)