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:
parent
010197a421
commit
002fdc48d4
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -49,7 +49,6 @@ const VTable Managed::static_vtbl =
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Managed::IsExecutionContext,
|
||||
Managed::IsString,
|
||||
Managed::IsObject,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) \
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue