From 7af1c2dc0e160652a9583cf1798720cd0f3d72f8 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 8 Oct 2015 10:06:06 +0200 Subject: Give SquareButton types a side property to mediate being square. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We shouldn't be setting width and height for each square; we should only need to set their side, which determines their width and height - so that they're actually square ! More pertinently, this could later serve as an illustration of how to use properties and bindings. Ideally, we'd do this in some way that actually ensures setting width or height changes side; but the simple approach will do for now. Change-Id: I0df89e11221dde5d1d2930c4a779b59cf0d46654 Reviewed-by: Topi Reiniƶ --- src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc | 8 +++++--- src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc | 3 ++- src/qml/doc/src/qmllanguageref/syntax/signals.qdoc | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/qml') diff --git a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc index 4b4b25796c..03a7ddfb19 100644 --- a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc @@ -43,7 +43,8 @@ For example, below is a document that declares a \l Rectangle with a child \l Mo import QtQuick 2.0 Rectangle { - width: 100; height: 100 + property int side: 100 + width: side; height: side color: "red" MouseArea { @@ -87,7 +88,7 @@ For example, the root object type in the \c SquareButton.qml file above is \l Re import QtQuick 2.0 Column { - SquareButton { width: 50; height: 50 } + SquareButton { side: 50 } SquareButton { x: 50; color: "blue" } SquareButton { radius: 10 } } @@ -112,7 +113,8 @@ Rectangle { root.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1) } - width: 100; height: 100 + property int side: 100 + width: side; height: side color: "red" MouseArea { diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index b0e262d2b9..b136a0e92f 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -724,7 +724,8 @@ Rectangle { signal activated(real xPosition, real yPosition) signal deactivated - width: 100; height: 100 + property int side: 100 + width: side; height: side MouseArea { anchors.fill: parent diff --git a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc index 602b202ed4..4a022f2b0b 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc @@ -187,7 +187,8 @@ Rectangle { signal activated(real xPosition, real yPosition) - width: 100; height: 100 + property int side: 100 + width: side; height: side MouseArea { anchors.fill: parent -- cgit v1.2.3 From ad48b299b7fe0bbed2749adc66725e4f12661f79 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 16 Sep 2016 14:30:14 +0200 Subject: Add a facility to version type information for debugging This serves the same purpose as qtbase/corelib/global/qhooks.cpp, but is meant to be in sync with changes in Qt Declarative internals. Change-Id: I5a4a7d9ca5c340367581749e05d09380590c46fb Reviewed-by: Ulf Hermann --- src/qml/debugger/qqmldebug.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/qml') diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp index 35dc110e9a..ea98bb16fa 100644 --- a/src/qml/debugger/qqmldebug.cpp +++ b/src/qml/debugger/qqmldebug.cpp @@ -119,4 +119,22 @@ bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, return false; } +enum { HookCount = 3 }; + +// Only add to the end, and bump version if you do. +quintptr Q_QML_EXPORT qtDeclarativeHookData[] = { + // Version of this Array. Bump if you add to end. + 1, + + // Number of entries in this array. + HookCount, + + // TypeInformationVersion, an integral value, bumped whenever private + // object sizes or member offsets that are used in Qt Creator's + // data structure "pretty printing" change. + 1 +}; + +Q_STATIC_ASSERT(HookCount == sizeof(qtDeclarativeHookData) / sizeof(qtDeclarativeHookData[0])); + QT_END_NAMESPACE -- cgit v1.2.3 From 2afb54fb51091765f79548b0b057795bc3c6eb38 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 23 Sep 2016 11:34:12 +0200 Subject: V4: Free up 2 address bits in 64bit mode This allows for the OS to use 49 address bits. It also maps JS Undefined to the C++ nullptr on 64bit. Task-number: QTBUG-54822 Change-Id: I7cc90620f499be1506a61aac77d72d067308838c Reviewed-by: Lars Knoll --- src/qml/debugger/qqmldebug.cpp | 2 +- src/qml/jit/qv4assembler.cpp | 38 +++++- src/qml/jit/qv4assembler_p.h | 5 + src/qml/jit/qv4isel_masm.cpp | 98 ++++++++++---- src/qml/jit/qv4isel_masm_p.h | 4 +- src/qml/jsruntime/qv4scopedvalue_p.h | 2 +- src/qml/jsruntime/qv4value_p.h | 246 ++++++++++++++++++++--------------- src/qml/jsruntime/qv4vme_moth.cpp | 26 ++-- 8 files changed, 269 insertions(+), 152 deletions(-) (limited to 'src/qml') diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp index ea98bb16fa..e864469da6 100644 --- a/src/qml/debugger/qqmldebug.cpp +++ b/src/qml/debugger/qqmldebug.cpp @@ -132,7 +132,7 @@ quintptr Q_QML_EXPORT qtDeclarativeHookData[] = { // TypeInformationVersion, an integral value, bumped whenever private // object sizes or member offsets that are used in Qt Creator's // data structure "pretty printing" change. - 1 + 2 }; Q_STATIC_ASSERT(HookCount == sizeof(qtDeclarativeHookData) / sizeof(qtDeclarativeHookData[0])); diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 929726f4b7..b7dbc81f90 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -133,8 +133,30 @@ void Assembler::generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBl generateCJumpOnCompare(NotEqual, reg, TrustedImm32(0), currentBlock, trueBlock, falseBlock); } -void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left,TrustedImm32 right, - IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, +#ifdef QV4_USE_64_BIT_VALUE_ENCODING +void Assembler::generateCJumpOnCompare(RelationalCondition cond, + RegisterID left, + TrustedImm64 right, + IR::BasicBlock *currentBlock, + IR::BasicBlock *trueBlock, + IR::BasicBlock *falseBlock) +{ + if (trueBlock == _nextBlock) { + Jump target = branch64(invert(cond), left, right); + addPatch(falseBlock, target); + } else { + Jump target = branch64(cond, left, right); + addPatch(trueBlock, target); + jumpToBlock(currentBlock, falseBlock); + } +} +#endif + +void Assembler::generateCJumpOnCompare(RelationalCondition cond, + RegisterID left, + TrustedImm32 right, + IR::BasicBlock *currentBlock, + IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock) { if (trueBlock == _nextBlock) { @@ -147,8 +169,11 @@ void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left } } -void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left, RegisterID right, - IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, +void Assembler::generateCJumpOnCompare(RelationalCondition cond, + RegisterID left, + RegisterID right, + IR::BasicBlock *currentBlock, + IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock) { if (trueBlock == _nextBlock) { @@ -334,9 +359,8 @@ Assembler::Jump Assembler::genTryDoubleConversion(IR::Expr *src, Assembler::FPRe // not an int, check if it's a double: isNoInt.link(this); #ifdef QV4_USE_64_BIT_VALUE_ENCODING - and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister); - Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister, - Assembler::TrustedImm32(0)); + rshift32(TrustedImm32(Value::IsDoubleTag_Shift), ScratchRegister); + Assembler::Jump isNoDbl = branch32(Equal, ScratchRegister, TrustedImm32(0)); #else and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister); Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister, diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 532a3114f2..ba9ca66935 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -374,6 +374,11 @@ public: void addPatch(DataLabelPtr patch, IR::BasicBlock *target); void generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); +#ifdef QV4_USE_64_BIT_VALUE_ENCODING + void generateCJumpOnCompare(RelationalCondition cond, RegisterID left, TrustedImm64 right, + IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, + IR::BasicBlock *falseBlock); +#endif void generateCJumpOnCompare(RelationalCondition cond, RegisterID left, TrustedImm32 right, IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index b6df5fb08c..1913b398eb 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -703,7 +703,7 @@ void InstructionSelection::loadString(const QString &str, IR::Expr *target) #else _as->store32(Assembler::ReturnValueRegister, destAddr); destAddr.offset += 4; - _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type), destAddr); + _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type_Internal), destAddr); #endif } @@ -1103,7 +1103,7 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe // not an int, check if it's NOT a double: isNoInt.link(_as); #ifdef QV4_USE_64_BIT_VALUE_ENCODING - _as->and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister); + _as->rshift32(Assembler::TrustedImm32(Value::IsDoubleTag_Shift), Assembler::ScratchRegister); Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); #else @@ -1194,10 +1194,15 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe _as->load64(addr, Assembler::ScratchRegister); _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister); - // check if it's a number - _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ScratchRegister); - Assembler::Jump isInt = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(1)); - Assembler::Jump fallback = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); + // check if it's integer convertible + _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsIntegerConvertible_Shift), Assembler::ScratchRegister); + Assembler::Jump isIntConvertible = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(3)); + + // nope, not integer convertible, so check for a double: + _as->urshift64(Assembler::TrustedImm32( + QV4::Value::IsDoubleTag_Shift - QV4::Value::IsIntegerConvertible_Shift), + Assembler::ScratchRegister); + Assembler::Jump fallback = _as->branch32(Assembler::GreaterThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); // it's a double _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister); @@ -1212,7 +1217,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt, _as->loadAddress(Assembler::ScratchRegister, source)); - isInt.link(_as); + isIntConvertible.link(_as); success.link(_as); IR::Temp *targetTemp = target->asTemp(); if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) { @@ -1784,9 +1789,9 @@ void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *tr { Q_ASSERT(binop->op == IR::OpStrictEqual || binop->op == IR::OpStrictNotEqual); - if (visitCJumpStrictNullUndefined(IR::NullType, binop, trueBlock, falseBlock)) + if (visitCJumpStrictNull(binop, trueBlock, falseBlock)) return; - if (visitCJumpStrictNullUndefined(IR::UndefinedType, binop, trueBlock, falseBlock)) + if (visitCJumpStrictUndefined(binop, trueBlock, falseBlock)) return; if (visitCJumpStrictBool(binop, trueBlock, falseBlock)) return; @@ -1802,16 +1807,14 @@ void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *tr } // Only load the non-null temp. -bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, IR::Binop *binop, - IR::BasicBlock *trueBlock, - IR::BasicBlock *falseBlock) +bool InstructionSelection::visitCJumpStrictNull(IR::Binop *binop, + IR::BasicBlock *trueBlock, + IR::BasicBlock *falseBlock) { - Q_ASSERT(nullOrUndef == IR::NullType || nullOrUndef == IR::UndefinedType); - IR::Expr *varSrc = 0; - if (binop->left->type == IR::VarType && binop->right->type == nullOrUndef) + if (binop->left->type == IR::VarType && binop->right->type == IR::NullType) varSrc = binop->left; - else if (binop->left->type == nullOrUndef && binop->right->type == IR::VarType) + else if (binop->left->type == IR::NullType && binop->right->type == IR::VarType) varSrc = binop->right; if (!varSrc) return false; @@ -1822,7 +1825,7 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I } if (IR::Const *c = varSrc->asConst()) { - if (c->type == nullOrUndef) + if (c->type == IR::NullType) _as->jumpToBlock(_block, trueBlock); else _as->jumpToBlock(_block, falseBlock); @@ -1835,9 +1838,54 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I _as->load32(tagAddr, tagReg); Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal - : Assembler::NotEqual; - const Assembler::TrustedImm32 tag(nullOrUndef == IR::NullType ? int(QV4::Value::Null_Type_Internal) - : int(QV4::Value::Undefined_Type)); + : Assembler::NotEqual; + const Assembler::TrustedImm32 tag(QV4::Value::Null_Type_Internal); + _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock); + return true; +} + +bool InstructionSelection::visitCJumpStrictUndefined(IR::Binop *binop, + IR::BasicBlock *trueBlock, + IR::BasicBlock *falseBlock) +{ + IR::Expr *varSrc = 0; + if (binop->left->type == IR::VarType && binop->right->type == IR::UndefinedType) + varSrc = binop->left; + else if (binop->left->type == IR::UndefinedType && binop->right->type == IR::VarType) + varSrc = binop->right; + if (!varSrc) + return false; + + if (varSrc->asTemp() && varSrc->asTemp()->kind == IR::Temp::PhysicalRegister) { + _as->jumpToBlock(_block, falseBlock); + return true; + } + + if (IR::Const *c = varSrc->asConst()) { + if (c->type == IR::UndefinedType) + _as->jumpToBlock(_block, trueBlock); + else + _as->jumpToBlock(_block, falseBlock); + return true; + } + + Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal + : Assembler::NotEqual; + const Assembler::RegisterID tagReg = Assembler::ScratchRegister; +#ifdef QV4_USE_64_BIT_VALUE_ENCODING + Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, varSrc); + _as->load64(addr, tagReg); + const Assembler::TrustedImm64 tag(0); +#else // !QV4_USE_64_BIT_VALUE_ENCODING + Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc); + _as->load32(tagAddr, tagReg); + Assembler::Jump j = _as->branch32(Assembler::invert(cond), tagReg, Assembler::TrustedImm32(0)); + _as->addPatch(falseBlock, j); + + tagAddr.offset += 4; + _as->load32(tagAddr, tagReg); + const Assembler::TrustedImm32 tag(QV4::Value::Managed_Type_Internal); +#endif _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock); return true; } @@ -1928,10 +1976,14 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin if (binop->op == IR::OpNotEqual) qSwap(trueBlock, falseBlock); Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Null_Type_Internal))); - Assembler::Jump isUndefined = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Undefined_Type))); + Assembler::Jump isNotUndefinedTag = _as->branch32(Assembler::NotEqual, tagReg, Assembler::TrustedImm32(int(QV4::Value::Managed_Type_Internal))); + tagAddr.offset -= 4; + _as->load32(tagAddr, tagReg); + Assembler::Jump isNotUndefinedValue = _as->branch32(Assembler::NotEqual, tagReg, Assembler::TrustedImm32(0)); _as->addPatch(trueBlock, isNull); - _as->addPatch(trueBlock, isUndefined); - _as->jumpToBlock(_block, falseBlock); + _as->addPatch(falseBlock, isNotUndefinedTag); + _as->addPatch(falseBlock, isNotUndefinedValue); + _as->jumpToBlock(_block, trueBlock); return true; } diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 6e9b02b034..f6d9364066 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -166,8 +166,8 @@ protected: bool visitCJumpSInt32(IR::AluOp op, IR::Expr *left, IR::Expr *right, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse); void visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); - bool visitCJumpStrictNullUndefined(IR::Type nullOrUndef, IR::Binop *binop, - IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); + bool visitCJumpStrictNull(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); + bool visitCJumpStrictUndefined(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); bool visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); bool visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 0b063ee4b8..ca23f83cfd 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -309,7 +309,7 @@ struct ScopedCallData { { int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value); ptr = reinterpret_cast(scope.alloc(size)); - ptr->tag = QV4::Value::Integer_Type; + ptr->tag = QV4::Value::Integer_Type_Internal; ptr->argc = argc; } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 5abf5ad9e8..02425c52a5 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -70,23 +70,85 @@ private: /* We use two different ways of encoding JS values. One for 32bit and one for 64bit systems. - In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double NaN (actually -qNaN) - is indicated by a number that has the top 13 bits set. The other values are usually set to 0 by the - processor, and are thus free for us to store other data. We keep pointers in there for managed objects, - and encode the other types using the free space given to use by the unused bits for NaN values. This also - works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory. - - On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that - will make the number a NaN. The Masks below are used for encoding the other types. - - On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will get encoded - with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These - can be used, as the highest valid pointer on a 64 bit system is 2^48-1. - - If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer. - This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set). - - Bit 15-17 is then used to encode other immediates. + In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double + NaN (actually -qNaN) is indicated by a number that has the top 13 bits set, and for a + signalling NaN it is the top 14 bits. The other values are usually set to 0 by the + processor, and are thus free for us to store other data. We keep pointers in there for + managed objects, and encode the other types using the free space given to use by the unused + bits for NaN values. This also works for pointers on 64 bit systems, as they all currently + only have 48 bits of addressable memory. (Note: we do leave the lower 49 bits available for + pointers.) + + On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value + that will make the number a NaN. The Masks below are used for encoding the other types. + + On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will + get encoded with bits 63-49 all set to 0. We then use bit 48 to distinguish between + managed/undefined (0), or Null/Int/Bool/Empty (1). So, storing a 49 bit pointer will leave + the top 15 bits 0, which is exactly the 'natural' representation of pointers. If bit 49 is + set, bit 48 indicates Empty (0) or integer-convertible (1). Then the 3 bit below that are + used to encode Null/Int/Bool. + + On both 32bit and 64bit, Undefined is encoded as a managed pointer with value 0. This is + the same as a nullptr. + + Specific bit-sequences: + 0 = always 0 + 1 = always 1 + x = stored value + a,b,c,d = specific bit values, see notes + + 64bit: + + 32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210 | + 66665555 55555544 44444444 33333333 33222222 22221111 11111100 00000000 | JS Value + ------------------------------------------------------------------------+-------------- + 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 | Undefined + 00000000 0000000x xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Managed (heap pointer) + a0000000 0000bc00 00000000 00000000 00000000 00000000 00000000 00000000 | NaN/Inf + dddddddd ddddddxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | double + 00000000 00000010 00000000 00000000 00000000 00000000 00000000 00000000 | empty (non-sparse array hole) + 00000000 00000011 10000000 00000000 00000000 00000000 00000000 00000000 | Null + 00000000 00000011 01000000 00000000 00000000 00000000 00000000 0000000x | Bool + 00000000 00000011 00100000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Int + + Notes: + - a: xor-ed signbit, always 1 for NaN + - bc, xor-ed values: 11 = inf, 10 = sNaN, 01 = qNaN, 00 = boxed value + - d: xor-ed bits, where at least one bit is set, so: (val >> (64-14)) > 0 + - Undefined maps to C++ nullptr, so the "default" initialization is the same for both C++ + and JS + - Managed has the left 15 bits set to 0, so: (val >> (64-15)) == 0 + - empty, Null, Bool, and Int have the left 14 bits set to 0, and bit 49 set to 1, + so: (val >> (64-15)) == 1 + - Null, Bool, and Int have bit 48 set, indicating integer-convertible + - xoring _val with NaNEncodeMask will convert to a double in "natural" representation, where + any non double results in a NaN + + 32bit: + + 32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210 | + 66665555 55555544 44444444 33333333 33222222 22221111 11111100 00000000 | JS Value + ------------------------------------------------------------------------+-------------- + 01111111 11111100 00000000 00000000 00000000 00000000 00000000 00000000 | Undefined + 01111111 11111100 00000000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Managed (heap pointer) + a1111111 1111bc00 00000000 00000000 00000000 00000000 00000000 00000000 | NaN/Inf + xddddddd ddddddxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | double + 01111111 11111110 00000000 00000000 00000000 00000000 00000000 00000000 | empty (non-sparse array hole) + 01111111 11111111 10000000 00000000 00000000 00000000 00000000 00000000 | Null + 01111111 11111111 01000000 00000000 00000000 00000000 00000000 0000000x | Bool + 01111111 11111111 00100000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Int + + Notes: + - the upper 32 bits are the tag, the lower 32 bits the value + - Undefined has a nullptr in the value, Managed has a non-nullptr stored in the value + - a: sign bit, always 0 for NaN + - b,c: 00=inf, 01 = sNaN, 10 = qNaN, 11 = boxed value + - d: stored double value, as long as not *all* of them are 1, because that's a boxed value + (see above) + - empty, Null, Bool, and Int have bit 63 set to 0, bits 62-50 set to 1 (same as undefined + and managed), and bit 49 set to 1 (where undefined and managed have it set to 0) + - Null, Bool, and Int have bit 48 set, indicating integer-convertible */ quint64 _val; @@ -137,7 +199,7 @@ public: { quint32 v; memcpy(&v, &b, 4); - setTagValue(Managed_Type, v); + setTagValue(Managed_Type_Internal, v); } #endif @@ -153,12 +215,32 @@ public: Q_ALWAYS_INLINE void setEmpty() { - setTagValue(Empty_Type, value()); + setTagValue(Empty_Type_Internal, value()); } Q_ALWAYS_INLINE void setEmpty(int i) { - setTagValue(Empty_Type, quint32(i)); + setTagValue(Empty_Type_Internal, quint32(i)); + } + + enum Type { + Undefined_Type, + Managed_Type, + Empty_Type, + Integer_Type, + Boolean_Type, + Null_Type, + Double_Type + }; + + inline Type type() const { + if (isUndefined()) return Undefined_Type; + if (isManaged()) return Managed_Type; + if (isEmpty()) return Empty_Type; + if (isInteger()) return Integer_Type; + if (isBoolean()) return Boolean_Type; + if (isNull()) return Null_Type; + Q_ASSERT(isDouble()); return Double_Type; } #ifndef QV4_USE_64_BIT_VALUE_ENCODING @@ -166,101 +248,64 @@ public: SilentNaNBit = 0x00040000, NaN_Mask = 0x7ff80000, NotDouble_Mask = 0x7ffa0000, - Type_Mask = 0xffffc000, - Immediate_Mask = NotDouble_Mask | 0x00004000 | SilentNaNBit, - IsNullOrUndefined_Mask = Immediate_Mask | 0x08000, + Immediate_Mask = NotDouble_Mask | 0x00020000u | SilentNaNBit, Tag_Shift = 32 }; - enum ValueType { - Undefined_Type = Immediate_Mask | 0x00000, - Null_Type = Immediate_Mask | 0x10000, - Boolean_Type = Immediate_Mask | 0x08000, - Integer_Type = Immediate_Mask | 0x18000, - Managed_Type = NotDouble_Mask | 0x00000 | SilentNaNBit, - Empty_Type = NotDouble_Mask | 0x18000 | SilentNaNBit - }; - - enum ImmediateFlags { - ConvertibleToInt = Immediate_Mask | 0x1 - }; - - enum ValueTypeInternal { - Null_Type_Internal = Null_Type | ConvertibleToInt, - Boolean_Type_Internal = Boolean_Type | ConvertibleToInt, - Integer_Type_Internal = Integer_Type | ConvertibleToInt, + enum { + Managed_Type_Internal = NotDouble_Mask }; #else - static const quint64 NaNEncodeMask = 0xffff800000000000ll; - static const quint64 IsInt32Mask = 0x0002000000000000ll; - static const quint64 IsDoubleMask = 0xfffc000000000000ll; - static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask; - static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll; - static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll; - static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask; + static const quint64 NaNEncodeMask = 0xfffc000000000000ll; + static const quint64 Immediate_Mask = 0x00020000u; // bit 49 enum Masks { NaN_Mask = 0x7ff80000, - Type_Mask = 0xffff8000, - IsDouble_Mask = 0xfffc0000, - Immediate_Mask = 0x00018000, - IsNullOrUndefined_Mask = 0x00008000, - IsNullOrBoolean_Mask = 0x00010000, - Tag_Shift = 32 - }; - enum ValueType { - Undefined_Type = IsNullOrUndefined_Mask, - Null_Type = IsNullOrUndefined_Mask|IsNullOrBoolean_Mask, - Boolean_Type = IsNullOrBoolean_Mask, - Integer_Type = 0x20000|IsNullOrBoolean_Mask, - Managed_Type = 0, - Empty_Type = Undefined_Type | 0x4000 }; enum { IsDouble_Shift = 64-14, - IsNumber_Shift = 64-15, - IsConvertibleToInt_Shift = 64-16, - IsManaged_Shift = 64-17 + IsManagedOrUndefined_Shift = 64-15, + IsIntegerConvertible_Shift = 64-16, + Tag_Shift = 32, + IsDoubleTag_Shift = IsDouble_Shift - Tag_Shift, + Managed_Type_Internal = 0 }; - - +#endif enum ValueTypeInternal { - Null_Type_Internal = Null_Type, - Boolean_Type_Internal = Boolean_Type, - Integer_Type_Internal = Integer_Type + Empty_Type_Internal = Immediate_Mask | 0, + ConvertibleToInt = Immediate_Mask | 0x10000u, // bit 48 + Null_Type_Internal = ConvertibleToInt | 0x08000u, + Boolean_Type_Internal = ConvertibleToInt | 0x04000u, + Integer_Type_Internal = ConvertibleToInt | 0x02000u }; -#endif - - inline unsigned type() const { - return tag() & Type_Mask; - } // used internally in property - inline bool isEmpty() const { return tag() == Empty_Type; } - - inline bool isUndefined() const { return tag() == Undefined_Type; } + inline bool isEmpty() const { return tag() == Empty_Type_Internal; } inline bool isNull() const { return tag() == Null_Type_Internal; } - inline bool isBoolean() const { return tag ()== Boolean_Type_Internal; } + inline bool isBoolean() const { return tag() == Boolean_Type_Internal; } + inline bool isInteger() const { return tag() == Integer_Type_Internal; } + inline bool isNullOrUndefined() const { return isNull() || isUndefined(); } + inline bool isNumber() const { return isDouble() || isInteger(); } + #ifdef QV4_USE_64_BIT_VALUE_ENCODING - inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; } + inline bool isUndefined() const { return _val == 0; } inline bool isDouble() const { return (_val >> IsDouble_Shift); } - inline bool isNumber() const { return (_val >> IsNumber_Shift); } - inline bool isManaged() const { return !(_val >> IsManaged_Shift); } - inline bool isNullOrUndefined() const { return ((_val >> IsManaged_Shift) & ~2) == 1; } - inline bool integerCompatible() const { return ((_val >> IsConvertibleToInt_Shift) & ~2) == 1; } + inline bool isManaged() const { return !isUndefined() && ((_val >> IsManagedOrUndefined_Shift) == 0); } + + inline bool integerCompatible() const { + return (_val >> IsIntegerConvertible_Shift) == 3; + } static inline bool integerCompatible(Value a, Value b) { return a.integerCompatible() && b.integerCompatible(); } static inline bool bothDouble(Value a, Value b) { return a.isDouble() && b.isDouble(); } - inline bool isNaN() const { return (tag() & 0x7fff8000) == 0x00078000; } + inline bool isNaN() const { return (tag() & 0x7ffc0000 ) == 0x00040000; } #else - inline bool isInteger() const { return tag() == Integer_Type_Internal; } + inline bool isUndefined() const { return tag() == Managed_Type_Internal && value() == 0; } inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; } - inline bool isNumber() const { return tag() == Integer_Type_Internal || (tag() & NotDouble_Mask) != NotDouble_Mask; } - inline bool isManaged() const { return tag() == Managed_Type; } - inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; } + inline bool isManaged() const { return tag() == Managed_Type_Internal && !isUndefined(); } inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; } static inline bool integerCompatible(Value a, Value b) { return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt; @@ -500,14 +545,14 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value inline Primitive Primitive::undefinedValue() { Primitive v; - v.setTagValue(Undefined_Type, 0); + v.setM(Q_NULLPTR); return v; } inline Primitive Primitive::emptyValue() { Primitive v; - v.setTagValue(Value::Empty_Type, 0); + v.setEmpty(0); return v; } @@ -535,7 +580,6 @@ inline Primitive Primitive::fromDouble(double d) inline Primitive Primitive::fromInt32(int i) { Primitive v; - v.setTagValue(Integer_Type_Internal, 0); v.setInt_32(i); return v; } @@ -553,31 +597,23 @@ inline Primitive Primitive::fromUInt32(uint i) struct Encode { static ReturnedValue undefined() { - return quint64(Value::Undefined_Type) << Value::Tag_Shift; + return Primitive::undefinedValue().rawValue(); } static ReturnedValue null() { - return quint64(Value::Null_Type_Internal) << Value::Tag_Shift; + return Primitive::nullValue().rawValue(); } Encode(bool b) { - val = (quint64(Value::Boolean_Type_Internal) << Value::Tag_Shift) | (uint)b; + val = Primitive::fromBoolean(b).rawValue(); } Encode(double d) { - Value v; - v.setDouble(d); - val = v.rawValue(); + val = Primitive::fromDouble(d).rawValue(); } Encode(int i) { - val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | (uint)i; + val = Primitive::fromInt32(i).rawValue(); } Encode(uint i) { - if (i <= INT_MAX) { - val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | i; - } else { - Value v; - v.setDouble(i); - val = v.rawValue(); - } + val = Primitive::fromUInt32(i).rawValue(); } Encode(ReturnedValue v) { val = v; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 024a72bde2..4688908286 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -563,7 +563,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code #endif // DO_TRACE_INSTR Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::callValue(engine, VALUE(instr.dest), callData)); @@ -573,7 +573,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::callProperty(engine, instr.name, callData)); @@ -582,7 +582,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallPropertyLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData)); @@ -592,7 +592,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData)); @@ -602,7 +602,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::callQmlContextObjectProperty(engine, instr.index, callData)); @@ -611,7 +611,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallElement) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::callElement(engine, VALUE(instr.index), callData)); @@ -620,7 +620,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallActivationProperty) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::callActivationProperty(engine, instr.name, callData)); @@ -629,7 +629,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallGlobalLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::callGlobalLookup(engine, instr.index, callData)); @@ -735,7 +735,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CreateValue) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::constructValue(engine, VALUE(instr.func), callData)); @@ -744,7 +744,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CreateProperty) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::constructProperty(engine, instr.name, callData)); @@ -753,7 +753,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(ConstructPropertyLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, Runtime::constructPropertyLookup(engine, instr.index, callData)); @@ -762,7 +762,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CreateActivationProperty) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::constructActivationProperty(engine, instr.name, callData)); @@ -771,7 +771,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(ConstructGlobalLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::constructGlobalLookup(engine, instr.index, callData)); -- cgit v1.2.3 From 3a45458b96bdcbccc189aabf668e998ea03be46f Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 28 Sep 2016 00:09:05 +0200 Subject: Fix crash on Array.prototype.join.call(0) We (incorrectly) didn't check the return value to make sure we had a valid self. At the same time, rename the self variable to match up with other methods. Task-number: QTBUG-53672 Change-Id: Ia0ae5a553e49c4c3b2834c7fdf649fe6373951a2 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arrayobject.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 25d3d9329b..324f2c7bf2 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -178,6 +178,10 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) { Scope scope(ctx); ScopedValue arg(scope, ctx->argument(0)); + ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + + if (!instance) + return ctx->d()->engine->newString()->asReturnedValue(); QString r4; if (arg->isUndefined()) @@ -185,8 +189,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) else r4 = arg->toQString(); - ScopedObject self(scope, ctx->thisObject()); - ScopedValue length(scope, self->get(ctx->d()->engine->id_length())); + ScopedValue length(scope, instance->get(ctx->d()->engine->id_length())); const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32(); if (!r2) @@ -195,7 +198,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) QString R; // ### FIXME - if (ArrayObject *a = self->as()) { + if (ArrayObject *a = instance->as()) { ScopedValue e(scope); for (uint i = 0; i < a->getLength(); ++i) { if (i) @@ -212,7 +215,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) // crazy! // ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0"))); - ScopedValue r6(scope, self->get(name)); + ScopedValue r6(scope, instance->get(name)); if (!r6->isNullOrUndefined()) R = r6->toQString(); @@ -221,7 +224,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) R += r4; name = Primitive::fromDouble(k).toString(scope.engine); - r12 = self->get(name); + r12 = instance->get(name); if (scope.hasException()) return Encode::undefined(); -- cgit v1.2.3 From c9ffed92a0dee0ae00a9632177ea42f85ea8a48c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 2 May 2016 16:55:36 +0200 Subject: Fix crash with window-less QQuickItems Mark QQuickItem visual children directly in QQuickItem instead of relying on the item being a (grand) child of a window. [ChangeLog][QtQuick] Fix crash with QQuickItems created via JavaScript being garbage collected sometimes when they're not assigned to a window. This may happen even in qmlscene when between the creation of the root item and the assignment to the QQuickWindow the garbage collector runs. The previous approach of a persistent in QQuickView marking the visual item hierarchy relies on the existence of a view. The only thing left to do in the view and qml window implementation is enforcing the CppOwnership policy set on the content item in QQuickWindow by ensuring the presence of the JS wrapper, replacing the persistent with a weak value. This also introduces a new internal mechanism for QObject sub-classes to provide their own V4 JS wrapper types. Task-number: QTBUG-39888 Change-Id: Icd45a636a6d4e4528fc19165b13f4e1ca7967087 Reviewed-by: Erik Verbruggen --- src/qml/jsruntime/qv4qobjectwrapper.cpp | 10 ++++++++-- src/qml/jsruntime/qv4qobjectwrapper_p.h | 2 +- src/qml/qml/qqmldata_p.h | 2 +- src/qml/qml/qqmlengine.cpp | 11 ++++++----- src/qml/qml/qqmlpropertycache.cpp | 14 ++++++++++---- src/qml/qml/qqmlpropertycache_p.h | 16 ++++++++++++++++ 6 files changed, 42 insertions(+), 13 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 6be86e3bdb..246df4c4e9 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -671,8 +671,14 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b) ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) { - if (engine->jsEngine()) - QQmlData::ensurePropertyCache(engine->jsEngine(), object); + if (QJSEngine *jsEngine = engine->jsEngine()) { + if (QQmlPropertyCache *cache = QQmlData::ensurePropertyCache(jsEngine, object)) { + ReturnedValue result = QV4::Encode::null(); + void *args[] = { &result, &engine }; + if (cache->callJSFactoryMethod(object, args)) + return result; + } + } return (engine->memoryManager->allocObject(object))->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 0fc39b222f..6af86ef446 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -71,7 +71,7 @@ namespace Heap { struct QQmlValueTypeWrapper; -struct QObjectWrapper : Object { +struct Q_QML_EXPORT QObjectWrapper : Object { QObjectWrapper(QObject *object); QPointer object; }; diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index ef05dd1fd7..e0e5b221ec 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -217,7 +217,7 @@ public: static inline void flushPendingBinding(QObject *, int coreIndex); - static void ensurePropertyCache(QJSEngine *engine, QObject *object); + static QQmlPropertyCache *ensurePropertyCache(QJSEngine *engine, QObject *object); private: // For attachedProperties diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 8f22533472..5db918dd73 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1808,14 +1808,15 @@ void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex) QQmlData_setBit(this, obj, coreIndex * 2 + 1); } -void QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object) +QQmlPropertyCache *QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object) { Q_ASSERT(engine); QQmlData *ddata = QQmlData::get(object, /*create*/true); - if (ddata->propertyCache) - return; - ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object); - if (ddata->propertyCache) ddata->propertyCache->addref(); + if (!ddata->propertyCache){ + ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object); + if (ddata->propertyCache) ddata->propertyCache->addref(); + } + return ddata->propertyCache; } void QQmlEnginePrivate::sendQuit() diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index e8c9989fdf..be730c7ac9 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -234,7 +234,7 @@ Creates a new empty QQmlPropertyCache. QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e) : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false), - _metaObject(0), argumentsCache(0) + _metaObject(0), argumentsCache(0), _jsFactoryMethodIndex(-1) { Q_ASSERT(engine); } @@ -245,7 +245,7 @@ Creates a new QQmlPropertyCache of \a metaObject. QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject) : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false), - _metaObject(0), argumentsCache(0) + _metaObject(0), argumentsCache(0), _jsFactoryMethodIndex(-1) { Q_ASSERT(engine); Q_ASSERT(metaObject); @@ -518,10 +518,16 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, for (int ii = 0; ii < classInfoCount; ++ii) { int idx = ii + classInfoOffset; - if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) { + const char * const classInfoName = metaObject->classInfo(idx).name(); + if (0 == qstrcmp(classInfoName, "qt_HasQmlAccessors")) { hasFastProperty = true; - } else if (0 == qstrcmp(metaObject->classInfo(idx).name(), "DefaultProperty")) { + } else if (0 == qstrcmp(classInfoName, "DefaultProperty")) { _defaultPropertyName = QString::fromUtf8(metaObject->classInfo(idx).value()); + } else if (0 == qstrcmp(classInfoName, "qt_QmlJSWrapperFactoryMethod")) { + const char * const factoryMethod = metaObject->classInfo(idx).value(); + _jsFactoryMethodIndex = metaObject->indexOfSlot(factoryMethod); + if (_jsFactoryMethodIndex != -1) + _jsFactoryMethodIndex -= metaObject->methodOffset(); } } diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 610709ef7f..046e75ad3a 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -75,6 +75,8 @@ class QQmlPropertyCacheCreator; class QQmlPropertyRawData { public: + typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction; + enum Flag { NoFlags = 0x00000000, ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask @@ -322,6 +324,8 @@ public: void toMetaObjectBuilder(QMetaObjectBuilder &); + inline bool callJSFactoryMethod(QObject *object, void **args) const; + protected: virtual void destroy(); virtual void clear(); @@ -390,6 +394,7 @@ private: QByteArray _dynamicStringData; QString _defaultPropertyName; QQmlPropertyCacheMethodArguments *argumentsCache; + int _jsFactoryMethodIndex; }; // QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache. @@ -538,6 +543,17 @@ int QQmlPropertyCache::signalOffset() const return signalHandlerIndexCacheStart; } +bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const +{ + if (_jsFactoryMethodIndex != -1) { + _metaObject->d.static_metacall(object, QMetaObject::InvokeMetaMethod, _jsFactoryMethodIndex, args); + return true; + } + if (_parent) + return _parent->callJSFactoryMethod(object, args); + return false; +} + QQmlMetaObject::QQmlMetaObject() { } -- cgit v1.2.3 From 0d8a2831779ccb15984e2fe80be04e9856668434 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 30 Sep 2016 10:37:28 +0200 Subject: qv4jsonobject: Make use of QVariant::toString in stringification This covers a whole host of missing cases, notably QUrl stored in a QV4::Value. Task-number: QTBUG-50592 Change-Id: I8afd772046c7bfbbcf916a7e90a57be5257b9df8 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4jsonobject.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 2e5283c639..fa3eeba745 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "qv4string_p.h" #include @@ -726,6 +727,10 @@ QString Stringify::Str(const QString &key, const Value &v) return std::isfinite(d) ? value->toQString() : QStringLiteral("null"); } + if (const QV4::VariantObject *v = value->as()) { + return v->d()->data.toString(); + } + o = value->asReturnedValue(); if (o) { if (!o->as()) { -- cgit v1.2.3 From 4d375f3f2b95bfcb322402df3525db6cc7a723ce Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 4 Oct 2016 11:42:10 +0200 Subject: QML: Clear weak references on Object destruction for C++-owned QObjects Otherwise a re-use of the C++-owned QObject will have a back reference to a possibly GCed QV4::QObjectWrapper, which results in exciting behavior. Task-number: QTBUG-46263 Change-Id: Iff0e36f9e67c01abd02cfb5a89605d0f26ddb0de Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4qobjectwrapper.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 246df4c4e9..77de84bf90 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1042,6 +1042,10 @@ void QObjectWrapper::destroyObject(bool lastCall) delete h->object; else h->object->deleteLater(); + } else { + // If the object is C++-owned, we still have to release the weak reference we have + // to it. + ddata->jsWrapper.clear(); } } } -- cgit v1.2.3 From a166367bd877a55e552e3dfe5cf2ee7fa1561100 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 5 Oct 2016 12:18:20 +0200 Subject: QML: Move the ScarceResourceData from VariantObject onto the heap So now VariantObject is nearly a trivial struct. Change-Id: Ifc54c04d9686c03e12066c5287823dd3b1315d2a Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 8 +++---- src/qml/jsruntime/qv4variantobject.cpp | 29 +++++++++++------------ src/qml/jsruntime/qv4variantobject_p.h | 15 ++++++++++-- src/qml/qml/qqmlbinding.cpp | 2 +- src/qml/qml/qqmlvaluetypewrapper.cpp | 2 +- src/qml/qml/qqmlvmemetaobject.cpp | 42 +++++++++++++++++----------------- 6 files changed, 55 insertions(+), 43 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index e81292f598..7b33cec1f1 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1079,7 +1079,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int QV4::Scope scope(e); if (const QV4::VariantObject *v = value.as()) - return v->d()->data; + return v->d()->data(); if (typeHint == QVariant::Bool) return QVariant(value.toBoolean()); @@ -1693,7 +1693,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data) return true; if (value->as() && name.endsWith('*')) { int valueType = QMetaType::type(name.left(name.size()-1)); - QVariant &var = value->as()->d()->data; + QVariant &var = value->as()->d()->data(); if (valueType == var.userType()) { // We have T t, T* is requested, so return &t. *reinterpret_cast(data) = var.data(); @@ -1705,7 +1705,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data) while (proto) { bool canCast = false; if (QV4::VariantObject *vo = proto->as()) { - const QVariant &v = vo->d()->data; + const QVariant &v = vo->d()->data(); canCast = (type == v.userType()) || (valueType && (valueType == v.userType())); } else if (proto->as()) { @@ -1760,7 +1760,7 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const Value &value) QV4::Scoped v(scope, value); if (v) { - QVariant variant = v->d()->data; + QVariant variant = v->d()->data(); int type = variant.userType(); if (type == QMetaType::QObjectStar) return *reinterpret_cast(variant.constData()); diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index 444c0a37e0..eff4db268c 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -52,18 +52,19 @@ DEFINE_OBJECT_VTABLE(VariantObject); Heap::VariantObject::VariantObject() { + scarceData = new ExecutionEngine::ScarceResourceData; } Heap::VariantObject::VariantObject(const QVariant &value) { - data = value; + scarceData = new ExecutionEngine::ScarceResourceData(value); if (isScarce()) - internalClass->engine->scarceResources.insert(this); + removeVmePropertyReference(); } bool VariantObject::Data::isScarce() const { - QVariant::Type t = data.type(); + QVariant::Type t = data().type(); return t == QVariant::Pixmap || t == QVariant::Image; } @@ -73,10 +74,10 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other) QV4::VariantObject *lv = static_cast(m); if (QV4::VariantObject *rv = other->as()) - return lv->d()->data == rv->d()->data; + return lv->d()->data() == rv->d()->data(); if (QV4::QQmlValueTypeWrapper *v = other->as()) - return v->isEqual(lv->d()->data); + return v->isEqual(lv->d()->data()); return false; } @@ -87,7 +88,7 @@ void VariantObject::addVmePropertyReference() // remove from the ep->scarceResources list // since it is now no longer eligible to be // released automatically by the engine. - d()->node.remove(); + d()->addVmePropertyReference(); } } @@ -97,7 +98,7 @@ void VariantObject::removeVmePropertyReference() // and add to the ep->scarceResources list // since it is now eligible to be released // automatically by the engine. - internalClass()->engine->scarceResources.insert(d()); + d()->removeVmePropertyReference(); } } @@ -115,7 +116,7 @@ QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->thisObject().as()); if (o && o->d()->isScarce()) - o->d()->node.remove(); + o->d()->addVmePropertyReference(); return Encode::undefined(); } @@ -125,8 +126,8 @@ QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx) Scoped o(scope, ctx->thisObject().as()); if (o) { if (o->d()->isScarce()) - o->d()->node.remove(); - o->d()->data = QVariant(); + o->d()->addVmePropertyReference(); + o->d()->data() = QVariant(); } return Encode::undefined(); } @@ -137,9 +138,9 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx) Scoped o(scope, ctx->thisObject().as()); if (!o) return Encode::undefined(); - QString result = o->d()->data.toString(); - if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String)) - result = QStringLiteral("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName())); + QString result = o->d()->data().toString(); + if (result.isEmpty() && !o->d()->data().canConvert(QVariant::String)) + result = QStringLiteral("QVariant(%0)").arg(QString::fromLatin1(o->d()->data().typeName())); return Encode(ctx->d()->engine->newString(result)); } @@ -148,7 +149,7 @@ QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx) Scope scope(ctx); Scoped o(scope, ctx->thisObject().as()); if (o) { - QVariant v = o->d()->data; + QVariant v = o->d()->data(); switch (v.type()) { case QVariant::Invalid: return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index e50706ef94..9b744faf75 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -64,16 +64,27 @@ namespace QV4 { namespace Heap { -struct VariantObject : Object, public ExecutionEngine::ScarceResourceData +struct VariantObject : Object { VariantObject(); VariantObject(const QVariant &value); ~VariantObject() { + Q_ASSERT(scarceData); if (isScarce()) - node.remove(); + addVmePropertyReference(); + delete scarceData; } bool isScarce() const; int vmePropertyReferenceCount; + + const QVariant &data() const { return scarceData->data; } + QVariant &data() { return scarceData->data; } + + void addVmePropertyReference() { scarceData->node.remove(); } + void removeVmePropertyReference() { internalClass->engine->scarceResources.insert(scarceData); } + +private: + ExecutionEngine::ScarceResourceData *scarceData; }; } diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 90698c3b24..203bfec838 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -600,7 +600,7 @@ protected: resultMo = resultObject->metaObject(); } } else if (auto variant = result.as()) { - QVariant value = variant->d()->data; + QVariant value = variant->d()->data(); QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()); resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType()); if (resultMo.isNull()) diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 6b308374e6..2279b72cbe 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -230,7 +230,7 @@ bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other) QV4::QQmlValueTypeWrapper *lv = static_cast(m); if (QV4::VariantObject *rv = other->as()) - return lv->isEqual(rv->d()->data); + return lv->isEqual(rv->d()->data()); if (QV4::QQmlValueTypeWrapper *v = other->as()) return lv->isEqual(v->toVariant()); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 4f13b44fc0..b08a0e5087 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -503,9 +503,9 @@ QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id) QV4::Scope scope(cache->engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as(); - if (!v || v->d()->data.type() != QVariant::Url) + if (!v || v->d()->data().type() != QVariant::Url) return QUrl(); - return v->d()->data.value(); + return v->d()->data().value(); } QDate QQmlVMEMetaObject::readPropertyAsDate(int id) @@ -517,9 +517,9 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id) QV4::Scope scope(cache->engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as(); - if (!v || v->d()->data.type() != QVariant::Date) + if (!v || v->d()->data().type() != QVariant::Date) return QDate(); - return v->d()->data.value(); + return v->d()->data().value(); } QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id) @@ -531,9 +531,9 @@ QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id) QV4::Scope scope(cache->engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as(); - if (!v || v->d()->data.type() != QVariant::DateTime) + if (!v || v->d()->data().type() != QVariant::DateTime) return QDateTime(); - return v->d()->data.value(); + return v->d()->data().value(); } QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id) @@ -545,9 +545,9 @@ QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id) QV4::Scope scope(cache->engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as(); - if (!v || v->d()->data.type() != QVariant::SizeF) + if (!v || v->d()->data().type() != QVariant::SizeF) return QSizeF(); - return v->d()->data.value(); + return v->d()->data().value(); } QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id) @@ -559,9 +559,9 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id) QV4::Scope scope(cache->engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as(); - if (!v || v->d()->data.type() != QVariant::PointF) + if (!v || v->d()->data().type() != QVariant::PointF) return QPointF(); - return v->d()->data.value(); + return v->d()->data().value(); } QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id) @@ -586,12 +586,12 @@ QList *QQmlVMEMetaObject::readPropertyAsList(int id) QV4::Scope scope(cache->engine); QV4::Scoped v(scope, *(md->data() + id)); - if (!v || (int)v->d()->data.userType() != qMetaTypeId >()) { + if (!v || (int)v->d()->data().userType() != qMetaTypeId >()) { QVariant variant(qVariantFromValue(QList())); v = cache->engine->newVariantObject(variant); *(md->data() + id) = v; } - return static_cast *>(v->d()->data.data()); + return static_cast *>(v->d()->data().data()); } QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) @@ -603,9 +603,9 @@ QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) QV4::Scope scope(cache->engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as(); - if (!v || v->d()->data.type() != QVariant::RectF) + if (!v || v->d()->data().type() != QVariant::RectF) return QRectF(); - return v->d()->data.value(); + return v->d()->data().value(); } #if defined(Q_OS_WINRT) && defined(_M_ARM) @@ -740,7 +740,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { QVariant propertyAsVariant; if (QV4::VariantObject *v = (md->data() + id)->as()) - propertyAsVariant = v->d()->data; + propertyAsVariant = v->d()->data(); QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], fallbackMetaType); } break; @@ -816,10 +816,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (!v) { *(md->data() + id) = cache->engine->newVariantObject(QVariant()); v = (md->data() + id)->as(); - QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data); + QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data()); } - needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data); - QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data); + needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data()); + QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data()); } break; case QV4::CompiledData::Property::Var: @@ -1009,7 +1009,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) return QVariant::fromValue(wrapper->object()); const QV4::VariantObject *v = (md->data() + id)->as(); if (v) - return v->d()->data; + return v->d()->data(); return cache->engine->toVariant(*(md->data() + id), -1); } return QVariant(); @@ -1092,8 +1092,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) if (md) { QV4::VariantObject *v = (md->data() + id)->as(); needActivate = (!v || - v->d()->data.userType() != value.userType() || - v->d()->data != value); + v->d()->data().userType() != value.userType() || + v->d()->data() != value); if (v) v->removeVmePropertyReference(); *(md->data() + id) = cache->engine->newVariantObject(value); -- cgit v1.2.3 From 64afa01c32fc1824b280452ceb1ade4f655487f2 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 9 Sep 2016 10:06:31 +0200 Subject: QML: Introduce destroy() on Base subclasses This removes the destructors of subclasses of Base, making them nearly trivial. Change-Id: Ia6f7d467e87899b5ad37b8709a8f633a51689d59 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arraybuffer.cpp | 2 +- src/qml/jsruntime/qv4arraybuffer_p.h | 2 +- src/qml/jsruntime/qv4arraydata_p.h | 7 +--- src/qml/jsruntime/qv4context_p_p.h | 2 +- src/qml/jsruntime/qv4engine.cpp | 6 ++-- src/qml/jsruntime/qv4errorobject.cpp | 24 +++++++------- src/qml/jsruntime/qv4errorobject_p.h | 3 +- src/qml/jsruntime/qv4functionobject.cpp | 2 +- src/qml/jsruntime/qv4functionobject_p.h | 2 +- src/qml/jsruntime/qv4managed_p.h | 2 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 +- src/qml/jsruntime/qv4qobjectwrapper_p.h | 15 ++++++--- src/qml/jsruntime/qv4regexp.cpp | 12 ++++--- src/qml/jsruntime/qv4regexp_p.h | 7 ++-- src/qml/jsruntime/qv4runtime.cpp | 6 ++-- src/qml/jsruntime/qv4sequenceobject.cpp | 58 ++++++++++++++++++--------------- src/qml/jsruntime/qv4string_p.h | 2 +- src/qml/jsruntime/qv4variantobject_p.h | 2 +- src/qml/memory/qv4mm_p.h | 11 +++++-- src/qml/qml/qqmlcomponent.cpp | 13 +++++--- src/qml/qml/qqmlcontextwrapper.cpp | 11 ++++--- src/qml/qml/qqmlcontextwrapper_p.h | 6 ++-- src/qml/qml/qqmllistwrapper.cpp | 2 +- src/qml/qml/qqmllistwrapper_p.h | 2 +- src/qml/qml/qqmllocale.cpp | 44 ++++++++++++------------- src/qml/qml/qqmllocale_p.h | 7 ++-- src/qml/qml/qqmltypewrapper.cpp | 2 +- src/qml/qml/qqmltypewrapper_p.h | 2 +- src/qml/qml/qqmlxmlhttprequest.cpp | 33 +++++++++++-------- src/qml/types/qqmldelegatemodel.cpp | 11 ++++--- src/qml/types/qqmldelegatemodel_p_p.h | 2 +- 31 files changed, 168 insertions(+), 134 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 34c7746684..e88f17a658 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -112,7 +112,7 @@ Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array) data->ref.ref(); } -Heap::ArrayBuffer::~ArrayBuffer() +void Heap::ArrayBuffer::destroy() { if (!data->ref.deref()) QTypedArrayData::deallocate(data); diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index b552cef9f1..a5ca0f6bad 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -66,7 +66,7 @@ struct ArrayBufferCtor : FunctionObject { struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object { ArrayBuffer(size_t length); ArrayBuffer(const QByteArray& array); - ~ArrayBuffer(); + void destroy(); QTypedArrayData *data; uint byteLength() const { return data->size; } diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index d7ee4798b0..ba0cc7cb30 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -156,7 +156,7 @@ struct SimpleArrayData : public ArrayData { Q_STATIC_ASSERT(std::is_trivial::value); struct SparseArrayData : public ArrayData { - inline ~SparseArrayData(); + void destroy() { delete sparse; } uint mappedIndex(uint index) const { SparseArrayNode *n = sparse->findNode(index); @@ -287,11 +287,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData namespace Heap { -inline SparseArrayData::~SparseArrayData() -{ - delete sparse; -} - void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs) { Property *pd = getProperty(index); diff --git a/src/qml/jsruntime/qv4context_p_p.h b/src/qml/jsruntime/qv4context_p_p.h index 0da9f678ed..ca8dc0b518 100644 --- a/src/qml/jsruntime/qv4context_p_p.h +++ b/src/qml/jsruntime/qv4context_p_p.h @@ -69,7 +69,7 @@ QObject *QmlContext::qmlScope() const QQmlContextData *QmlContext::qmlContext() const { - return d()->qml->context; + return *d()->qml->context; } void QmlContext::takeContextOwnership() { diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 7b33cec1f1..f630dfaee0 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -744,7 +744,7 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const if (!ctx) return 0; - return ctx->qml->context.contextData(); + return ctx->qml->context->contextData(); } QVector ExecutionEngine::stackTrace(int frameLimit) const @@ -920,7 +920,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value) QV4::Scope scope(this); QV4::Scoped error(scope, value); if (!!error) - exceptionStackTrace = error->d()->stackTrace; + exceptionStackTrace = *error->d()->stackTrace; else exceptionStackTrace = stackTrace(); @@ -1153,7 +1153,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return str; } if (const QV4::QQmlLocaleData *ld = value.as()) - return ld->d()->locale; + return *ld->d()->locale; if (const QV4::DateObject *d = value.as()) return d->toQDateTime(); if (const ArrayBuffer *d = value.as()) diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 3763bf2613..bb5d32cbd7 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -69,6 +69,8 @@ using namespace QV4; Heap::ErrorObject::ErrorObject() { + stackTrace = nullptr; + Scope scope(internalClass->engine); Scoped e(scope, this); @@ -91,10 +93,10 @@ Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t) *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction(); *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined(); - e->d()->stackTrace = scope.engine->stackTrace(); - if (!e->d()->stackTrace.isEmpty()) { - *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source); - *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line); + e->d()->stackTrace = new StackTrace(scope.engine->stackTrace()); + if (!e->d()->stackTrace->isEmpty()) { + *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source); + *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line); } if (!message.isUndefined()) @@ -111,16 +113,16 @@ Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, in *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction(); *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined(); - e->d()->stackTrace = scope.engine->stackTrace(); + e->d()->stackTrace = new StackTrace(scope.engine->stackTrace()); StackFrame frame; frame.source = fileName; frame.line = line; frame.column = column; - e->d()->stackTrace.prepend(frame); + e->d()->stackTrace->prepend(frame); - if (!e->d()->stackTrace.isEmpty()) { - *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source); - *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line); + if (!e->d()->stackTrace->isEmpty()) { + *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source); + *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line); } if (!message.isUndefined()) @@ -156,10 +158,10 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx) return ctx->engine()->throwTypeError(); if (!This->d()->stack) { QString trace; - for (int i = 0; i < This->d()->stackTrace.count(); ++i) { + for (int i = 0; i < This->d()->stackTrace->count(); ++i) { if (i > 0) trace += QLatin1Char('\n'); - const StackFrame &frame = This->d()->stackTrace[i]; + const StackFrame &frame = This->d()->stackTrace->at(i); trace += frame.function + QLatin1Char('@') + frame.source; if (frame.line >= 0) trace += QLatin1Char(':') + QString::number(frame.line); diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 42a3d05d9f..206c7e6c59 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -76,9 +76,10 @@ struct ErrorObject : Object { ErrorObject(); ErrorObject(const Value &message, ErrorType t = Error); ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); + void destroy() { delete stackTrace; } ErrorType errorType; - StackTrace stackTrace; + StackTrace *stackTrace; Pointer stack; }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index e160dd8a36..aa8c7d6a81 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -136,7 +136,7 @@ Heap::FunctionObject::FunctionObject() } -Heap::FunctionObject::~FunctionObject() +void Heap::FunctionObject::destroy() { if (function) function->compilationUnit->release(); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 182b762606..f5a9376b9e 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -76,7 +76,7 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name); FunctionObject(ExecutionContext *scope, const ReturnedValue name); FunctionObject(); - ~FunctionObject(); + void destroy(); unsigned int formalParameterCount() { return function ? function->nFormals : 0; } unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 764a8e7f3f..b56155b5db 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -74,7 +74,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} #define V4_MANAGED_SIZE_TEST #endif -#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast(b)->~Data(); } +#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast(b)->destroy(); } #define V4_MANAGED_ITSELF(DataClass, superClass) \ diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 202b7d3525..c977573b9b 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1847,7 +1847,7 @@ Heap::QMetaObjectWrapper::QMetaObjectWrapper(const QMetaObject *metaObject) , constructorCount(0) {} -Heap::QMetaObjectWrapper::~QMetaObjectWrapper() +void Heap::QMetaObjectWrapper::destroy() { delete[] constructors; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 076f304fea..37397db55b 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -79,7 +79,7 @@ struct QQmlValueTypeWrapper; struct QObjectWrapper : Object { QObjectWrapper(QObject *object); - ~QObjectWrapper() { qObj.destroy(); } + void destroy() { qObj.destroy(); } QObject *object() const { return qObj.data(); } @@ -89,7 +89,13 @@ private: struct QObjectMethod : FunctionObject { QObjectMethod(QV4::ExecutionContext *scope); - ~QObjectMethod() { qObj.destroy(); } + void destroy() + { + propertyCache = nullptr; + qObj.destroy(); + FunctionObject::destroy(); + } + QQmlRefPointer propertyCache; int index; @@ -109,13 +115,13 @@ struct QMetaObjectWrapper : FunctionObject { int constructorCount; QMetaObjectWrapper(const QMetaObject* metaObject); - ~QMetaObjectWrapper(); + void destroy(); void ensureConstructorsCache(); }; struct QmlSignalHandler : Object { QmlSignalHandler(QObject *object, int signalIndex); - ~QmlSignalHandler() { qObj.destroy(); } + void destroy() { qObj.destroy(); } int signalIndex; QObject *object() const { return qObj.data(); } @@ -130,6 +136,7 @@ private: struct Q_QML_EXPORT QObjectWrapper : public Object { V4_OBJECT2(QObjectWrapper, Object) + V4_NEEDS_DESTROY enum RevisionMode { IgnoreRevision, CheckRevision }; diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 6d6d446ca2..7e2f4697c5 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -62,8 +62,8 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) WTF::String s(string); #if ENABLE(YARR_JIT) - if (!jitCode().isFallBack() && jitCode().has16BitCode()) - return uint(jitCode().execute(s.characters16(), start, s.length(), (int*)matchOffsets).start); + if (!jitCode()->isFallBack() && jitCode()->has16BitCode()) + return uint(jitCode()->execute(s.characters16(), start, s.length(), (int*)matchOffsets).start); #endif return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets); @@ -104,19 +104,23 @@ Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignor subPatternCount = yarrPattern.m_numSubpatterns; byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); #if ENABLE(YARR_JIT) + jitCode = new JSC::Yarr::YarrCodeBlock; if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) { JSC::JSGlobalData dummy(engine->regExpAllocator); - JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, jitCode); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, *jitCode); } #endif } -Heap::RegExp::~RegExp() +void Heap::RegExp::destroy() { if (cache) { RegExpCacheKey key(this); cache->remove(key); } +#if ENABLE(YARR_JIT) + delete jitCode; +#endif } void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index b99d717847..33ed1d1117 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -77,11 +77,12 @@ namespace Heap { struct RegExp : Base { RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); - ~RegExp(); + void destroy(); + QString pattern; OwnPtr byteCode; #if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock jitCode; + JSC::Yarr::YarrCodeBlock *jitCode; #endif RegExpCache *cache; int subPatternCount; @@ -102,7 +103,7 @@ struct RegExp : public Managed QString pattern() const { return d()->pattern; } OwnPtr &byteCode() { return d()->byteCode; } #if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock jitCode() const { return d()->jitCode; } + JSC::Yarr::YarrCodeBlock *jitCode() const { return d()->jitCode; } #endif RegExpCache *cache() const { return d()->cache; } int subPatternCount() const { return d()->subPatternCount; } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 88c1286c61..e65f4118fb 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1462,7 +1462,7 @@ ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) { const QmlContext &c = static_cast(context); - return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, captureRequired); + return QV4::QObjectWrapper::getProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, captureRequired); } ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) @@ -1480,7 +1480,7 @@ ReturnedValue Runtime::method_getQmlIdObject(ExecutionEngine *engine, const Valu { Scope scope(engine); const QmlContext &qmlContext = static_cast(c); - QQmlContextData *context = qmlContext.d()->qml->context; + QQmlContextData *context = *qmlContext.d()->qml->context; if (!context || index >= (uint)context->idValueCount) return Encode::undefined(); @@ -1500,7 +1500,7 @@ void Runtime::method_setQmlScopeObjectProperty(ExecutionEngine *engine, const Va void Runtime::method_setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) { const QmlContext &c = static_cast(context); - return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value); + return QV4::QObjectWrapper::setProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, value); } void Runtime::method_setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 59086c245c..fb9ef4a2b2 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -218,9 +218,12 @@ template struct QQmlSequence : Object { QQmlSequence(const Container &container); QQmlSequence(QObject *object, int propertyIndex); - ~QQmlSequence() { object.destroy(); } + void destroy() { + delete container; + object.destroy(); + } - mutable Container container; + mutable Container *container; QQmlQPointer object; int propertyIndex; bool isReference; @@ -260,10 +263,10 @@ public: loadReference(); } qint32 signedIdx = static_cast(index); - if (signedIdx < d()->container.count()) { + if (signedIdx < d()->container->count()) { if (hasProperty) *hasProperty = true; - return convertElementToValue(engine(), d()->container.at(signedIdx)); + return convertElementToValue(engine(), d()->container->at(signedIdx)); } if (hasProperty) *hasProperty = false; @@ -289,22 +292,22 @@ public: qint32 signedIdx = static_cast(index); - int count = d()->container.count(); + int count = d()->container->count(); typename Container::value_type element = convertValueToElement(value); if (signedIdx == count) { - d()->container.append(element); + d()->container->append(element); } else if (signedIdx < count) { - d()->container[signedIdx] = element; + (*d()->container)[signedIdx] = element; } else { /* according to ECMA262r3 we need to insert */ /* the value at the given index, increasing length to index+1. */ - d()->container.reserve(signedIdx + 1); + d()->container->reserve(signedIdx + 1); while (signedIdx > count++) { - d()->container.append(typename Container::value_type()); + d()->container->append(typename Container::value_type()); } - d()->container.append(element); + d()->container->append(element); } if (d()->isReference) @@ -324,7 +327,7 @@ public: loadReference(); } qint32 signedIdx = static_cast(index); - return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid; + return (signedIdx < d()->container->count()) ? QV4::Attr_Data : QV4::Attr_Invalid; } void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs) @@ -340,11 +343,11 @@ public: loadReference(); } - if (it->arrayIndex < static_cast(d()->container.count())) { + if (it->arrayIndex < static_cast(d()->container->count())) { *index = it->arrayIndex; ++it->arrayIndex; *attrs = QV4::Attr_Data; - p->value = convertElementToValue(engine(), d()->container.at(*index)); + p->value = convertElementToValue(engine(), d()->container->at(*index)); return; } QV4::Object::advanceIterator(this, it, name, index, p, attrs); @@ -362,12 +365,12 @@ public: } qint32 signedIdx = static_cast(index); - if (signedIdx >= d()->container.count()) + if (signedIdx >= d()->container->count()) return false; /* according to ECMA262r3 it should be Undefined, */ /* but we cannot, so we insert a default-value instead. */ - d()->container.replace(signedIdx, typename Container::value_type()); + d()->container->replace(signedIdx, typename Container::value_type()); if (d()->isReference) storeReference(); @@ -432,10 +435,10 @@ public: QV4::Scope scope(ctx); if (ctx->argc() == 1 && ctx->args()[0].as()) { CompareFunctor cf(ctx, ctx->args()[0]); - std::sort(d()->container.begin(), d()->container.end(), cf); + std::sort(d()->container->begin(), d()->container->end(), cf); } else { DefaultCompareFunctor cf; - std::sort(d()->container.begin(), d()->container.end(), cf); + std::sort(d()->container->begin(), d()->container->end(), cf); } if (d()->isReference) @@ -454,7 +457,7 @@ public: return QV4::Encode(0); This->loadReference(); } - return QV4::Encode(This->d()->container.count()); + return QV4::Encode(This->d()->container->count()); } static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx) @@ -478,23 +481,23 @@ public: } /* Determine whether we need to modify the sequence */ qint32 newCount = static_cast(newLength); - qint32 count = This->d()->container.count(); + qint32 count = This->d()->container->count(); if (newCount == count) { return QV4::Encode::undefined(); } else if (newCount > count) { /* according to ECMA262r3 we need to insert */ /* undefined values increasing length to newLength. */ /* We cannot, so we insert default-values instead. */ - This->d()->container.reserve(newCount); + This->d()->container->reserve(newCount); while (newCount > count++) { - This->d()->container.append(typename Container::value_type()); + This->d()->container->append(typename Container::value_type()); } } else { /* according to ECMA262r3 we need to remove */ /* elements until the sequence is the required length. */ while (newCount < count) { count--; - This->d()->container.removeAt(count); + This->d()->container->removeAt(count); } } /* write back if required. */ @@ -506,7 +509,7 @@ public: } QVariant toVariant() const - { return QVariant::fromValue(d()->container); } + { return QVariant::fromValue(*d()->container); } static QVariant toVariant(QV4::ArrayObject *array) { @@ -523,7 +526,7 @@ public: { Q_ASSERT(d()->object); Q_ASSERT(d()->isReference); - void *a[] = { &d()->container, 0 }; + void *a[] = { d()->container, 0 }; QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a); } @@ -533,7 +536,7 @@ public: Q_ASSERT(d()->isReference); int status = -1; QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding; - void *a[] = { &d()->container, 0, &status, &flags }; + void *a[] = { d()->container, 0, &status, &flags }; QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a); } @@ -555,7 +558,7 @@ public: template Heap::QQmlSequence::QQmlSequence(const Container &container) - : container(container) + : container(new Container(container)) , propertyIndex(-1) , isReference(false) { @@ -569,7 +572,8 @@ Heap::QQmlSequence::QQmlSequence(const Container &container) template Heap::QQmlSequence::QQmlSequence(QObject *object, int propertyIndex) - : propertyIndex(propertyIndex) + : container(new Container) + , propertyIndex(propertyIndex) , isReference(true) { this->object.init(object); diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index f347ea8897..50b7fb664a 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -73,7 +73,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base { #ifndef V4_BOOTSTRAP String(MemoryManager *mm, const QString &text); String(MemoryManager *mm, String *l, String *n, bool dummy); - ~String() { + void destroy() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); } diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 9b744faf75..5a6644bdcf 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -68,7 +68,7 @@ struct VariantObject : Object { VariantObject(); VariantObject(const QVariant &value); - ~VariantObject() { + void destroy() { Q_ASSERT(scarceData); if (isScarce()) addVmePropertyReference(); diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 6db5b54760..43cedbc165 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -256,24 +256,27 @@ public: template typename ManagedType::Data *alloc() { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(); + t->d_unchecked()->init(); return t->d(); } template typename ManagedType::Data *alloc(Arg1 arg1) { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1); + t->d_unchecked()->init(arg1); return t->d(); } template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2) { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2); @@ -283,6 +286,7 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3); @@ -301,9 +305,10 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5); + t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5); return t->d(); } diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 3cfbd7bed1..9a993d4ec3 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1059,8 +1059,8 @@ namespace Heap { struct QmlIncubatorObject : Object { QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); - ~QmlIncubatorObject() { parent.destroy(); } - QScopedPointer incubator; + inline void destroy(); + QQmlComponentIncubator *incubator; QQmlQPointer parent; QV4::Value valuemap; QV4::Value statusChanged; @@ -1389,7 +1389,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) r->d()->qmlContext = v4->qmlContext(); r->d()->parent = parent; - QQmlIncubator *incubator = r->d()->incubator.data(); + QQmlIncubator *incubator = r->d()->incubator; create(*incubator, creationContext()); if (incubator->status() == QQmlIncubator::Null) { @@ -1490,7 +1490,12 @@ QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode { parent.init(); qmlContext = nullptr; - incubator.reset(new QQmlComponentIncubator(this, m)); + incubator = new QQmlComponentIncubator(this, m); +} + +void QV4::Heap::QmlIncubatorObject::destroy() { + delete incubator; + parent.destroy(); } void QV4::QmlIncubatorObject::setInitialState(QObject *o) diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 13d708bc17..95ff7b866f 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -65,15 +65,16 @@ Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *sc : readOnly(true) , ownsContext(ownsContext) , isNullWrapper(false) - , context(context) { + this->context = new QQmlGuardedContextData(context); this->scopeObject.init(scopeObject); } -Heap::QmlContextWrapper::~QmlContextWrapper() +void Heap::QmlContextWrapper::destroy() { - if (context && ownsContext) - context->destroy(); + if (*context && ownsContext) + (*context)->destroy(); + delete context; scopeObject.destroy(); } @@ -120,7 +121,7 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr if (resource->d()->isNullWrapper) return Object::get(m, name, hasProperty); - if (v4->callingQmlContext() != resource->d()->context) + if (v4->callingQmlContext() != *resource->d()->context) return Object::get(m, name, hasProperty); result = Object::get(m, name, &hasProp); diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index 2b8c16f274..9e5ba4a10c 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -65,12 +65,12 @@ namespace Heap { struct QmlContextWrapper : Object { QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); - ~QmlContextWrapper(); + void destroy(); bool readOnly; bool ownsContext; bool isNullWrapper; - QQmlGuardedContextData context; + QQmlGuardedContextData *context; QQmlQPointer scopeObject; }; @@ -89,7 +89,7 @@ struct Q_QML_EXPORT QmlContextWrapper : Object } inline QObject *getScopeObject() const { return d()->scopeObject; } - inline QQmlContextData *getContext() const { return d()->context; } + inline QQmlContextData *getContext() const { return *d()->context; } void setReadOnly(bool b) { d()->readOnly = b; } diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 425a720867..4bc0e11340 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -60,7 +60,7 @@ Heap::QmlListWrapper::QmlListWrapper() o->setArrayType(Heap::ArrayData::Custom); } -Heap::QmlListWrapper::~QmlListWrapper() +void Heap::QmlListWrapper::destroy() { object.destroy(); } diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index 1107b957c9..18038d2a80 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -67,7 +67,7 @@ namespace Heap { struct QmlListWrapper : Object { QmlListWrapper(); - ~QmlListWrapper(); + void destroy(); QQmlQPointer object; QQmlListProperty property; int propertyType; diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 76752f509c..6f66475aa5 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -109,16 +109,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct if (ctx->argc() == 2) { if (ctx->args()[1].isString()) { QString format = ctx->args()[1].stringValue()->toQString(); - formattedDt = r->d()->locale.toString(dt, format); + formattedDt = r->d()->locale->toString(dt, format); } else if (ctx->args()[1].isNumber()) { quint32 intFormat = ctx->args()[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - formattedDt = r->d()->locale.toString(dt, format); + formattedDt = r->d()->locale->toString(dt, format); } else { V4THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format"); } } else { - formattedDt = r->d()->locale.toString(dt, enumFormat); + formattedDt = r->d()->locale->toString(dt, enumFormat); } return ctx->d()->engine->newString(formattedDt)->asReturnedValue(); @@ -154,16 +154,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext if (ctx->argc() == 2) { if (ctx->args()[1].isString()) { QString format = ctx->args()[1].stringValue()->toQString(); - formattedTime = r->d()->locale.toString(time, format); + formattedTime = r->d()->locale->toString(time, format); } else if (ctx->args()[1].isNumber()) { quint32 intFormat = ctx->args()[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - formattedTime = r->d()->locale.toString(time, format); + formattedTime = r->d()->locale->toString(time, format); } else { V4THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format"); } } else { - formattedTime = r->d()->locale.toString(time, enumFormat); + formattedTime = r->d()->locale->toString(time, enumFormat); } return ctx->d()->engine->newString(formattedTime)->asReturnedValue(); @@ -199,16 +199,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext if (ctx->argc() == 2) { if (ctx->args()[1].isString()) { QString format = ctx->args()[1].stringValue()->toQString(); - formattedDate = r->d()->locale.toString(date, format); + formattedDate = r->d()->locale->toString(date, format); } else if (ctx->args()[1].isNumber()) { quint32 intFormat = ctx->args()[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - formattedDate = r->d()->locale.toString(date, format); + formattedDate = r->d()->locale->toString(date, format); } else { V4THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format"); } } else { - formattedDate = r->d()->locale.toString(date, enumFormat); + formattedDate = r->d()->locale->toString(date, enumFormat); } return ctx->d()->engine->newString(formattedDate)->asReturnedValue(); @@ -237,16 +237,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext * if (ctx->argc() == 3) { if (ctx->args()[2].isString()) { QString format = ctx->args()[2].stringValue()->toQString(); - dt = r->d()->locale.toDateTime(dateString, format); + dt = r->d()->locale->toDateTime(dateString, format); } else if (ctx->args()[2].isNumber()) { quint32 intFormat = ctx->args()[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - dt = r->d()->locale.toDateTime(dateString, format); + dt = r->d()->locale->toDateTime(dateString, format); } else { V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format"); } } else { - dt = r->d()->locale.toDateTime(dateString, enumFormat); + dt = r->d()->locale->toDateTime(dateString, enumFormat); } return QV4::Encode(engine->newDateObject(dt)); @@ -278,16 +278,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallConte if (ctx->argc() == 3) { if (ctx->args()[2].isString()) { QString format = ctx->args()[2].stringValue()->toQString(); - tm = r->d()->locale.toTime(dateString, format); + tm = r->d()->locale->toTime(dateString, format); } else if (ctx->args()[2].isNumber()) { quint32 intFormat = ctx->args()[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - tm = r->d()->locale.toTime(dateString, format); + tm = r->d()->locale->toTime(dateString, format); } else { V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format"); } } else { - tm = r->d()->locale.toTime(dateString, enumFormat); + tm = r->d()->locale->toTime(dateString, enumFormat); } QDateTime dt; @@ -323,16 +323,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallConte if (ctx->argc() == 3) { if (ctx->args()[2].isString()) { QString format = ctx->args()[2].stringValue()->toQString(); - dt = r->d()->locale.toDate(dateString, format); + dt = r->d()->locale->toDate(dateString, format); } else if (ctx->args()[2].isNumber()) { quint32 intFormat = ctx->args()[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - dt = r->d()->locale.toDate(dateString, format); + dt = r->d()->locale->toDate(dateString, format); } else { V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format"); } } else { - dt = r->d()->locale.toDate(dateString, enumFormat); + dt = r->d()->locale->toDate(dateString, enumFormat); } return QV4::Encode(engine->newDateObject(QDateTime(dt))); @@ -393,7 +393,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext * prec = ctx->args()[2].toInt32(); } - return ctx->d()->engine->newString(r->d()->locale.toString(number, (char)format, prec))->asReturnedValue(); + return ctx->d()->engine->newString(r->d()->locale->toString(number, (char)format, prec))->asReturnedValue(); } QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallContext *ctx) @@ -423,7 +423,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallC symbol = ctx->args()[1].toQStringNoThrow(); } - return ctx->d()->engine->newString(r->d()->locale.toCurrencyString(number, symbol))->asReturnedValue(); + return ctx->d()->engine->newString(r->d()->locale->toCurrencyString(number, symbol))->asReturnedValue(); } QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext *ctx) @@ -441,7 +441,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); - locale = r->d()->locale; + locale = *r->d()->locale; numberIdx = 1; } @@ -813,7 +813,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale) QV4::Scope scope(v4); QV4LocaleDataDeletable *d = localeV4Data(scope.engine); QV4::Scoped wrapper(scope, v4->memoryManager->allocObject()); - wrapper->d()->locale = locale; + *wrapper->d()->locale = locale; QV4::ScopedObject p(scope, d->prototype.value()); wrapper->setPrototype(p); return wrapper.asReturnedValue(); diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 652a3ca0d4..4494fa9b53 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -143,8 +143,9 @@ namespace QV4 { namespace Heap { struct QQmlLocaleData : Object { - inline QQmlLocaleData() {} - QLocale locale; + inline QQmlLocaleData() { locale = new QLocale; } + void destroy() { delete locale; } + QLocale *locale; }; } @@ -161,7 +162,7 @@ struct QQmlLocaleData : public QV4::Object ctx->engine()->throwTypeError(); return 0; } - return &thisObject->d()->locale; + return thisObject->d()->locale; } static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx); diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 28c2588117..c8e2e5387c 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -61,7 +61,7 @@ Heap::QmlTypeWrapper::QmlTypeWrapper() object.init(); } -Heap::QmlTypeWrapper::~QmlTypeWrapper() +void Heap::QmlTypeWrapper::destroy() { if (typeNamespace) typeNamespace->release(); diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 7c5105b184..fe75aefca9 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -72,7 +72,7 @@ struct QmlTypeWrapper : Object { }; QmlTypeWrapper(); - ~QmlTypeWrapper(); + void destroy(); TypeNameMode mode; QQmlQPointer object; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 85e17525a5..5128fc0f08 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -175,17 +175,24 @@ namespace Heap { struct NamedNodeMap : Object { NamedNodeMap(NodeImpl *data, const QList &list); - ~NamedNodeMap() { + void destroy() { + delete listPtr; if (d) d->release(); } - QList list; // Only used in NamedNodeMap + QList &list() { + if (listPtr == nullptr) + listPtr = new QList; + return *listPtr; + } + + QList *listPtr; // Only used in NamedNodeMap NodeImpl *d; }; struct NodeList : Object { NodeList(NodeImpl *data); - ~NodeList() { + void destroy() { if (d) d->release(); } @@ -198,7 +205,7 @@ struct NodePrototype : Object { struct Node : Object { Node(NodeImpl *data); - ~Node() { + void destroy() { if (d) d->release(); } @@ -222,9 +229,9 @@ public: }; Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList &list) - : list(list) - , d(data) + : d(data) { + this->list() = list; if (d) d->addref(); } @@ -877,10 +884,10 @@ ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasPr const NamedNodeMap *r = static_cast(m); QV4::ExecutionEngine *v4 = r->engine(); - if ((int)index < r->d()->list.count()) { + if ((int)index < r->d()->list().count()) { if (hasProperty) *hasProperty = true; - return Node::create(v4, r->d()->list.at(index)); + return Node::create(v4, r->d()->list().at(index)); } if (hasProperty) *hasProperty = false; @@ -895,14 +902,14 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert name->makeIdentifier(v4); if (name->equals(v4->id_length())) - return Primitive::fromInt32(r->d()->list.count()).asReturnedValue(); + return Primitive::fromInt32(r->d()->list().count()).asReturnedValue(); QString str = name->toQString(); - for (int ii = 0; ii < r->d()->list.count(); ++ii) { - if (r->d()->list.at(ii)->name == str) { + for (int ii = 0; ii < r->d()->list().count(); ++ii) { + if (r->d()->list().at(ii)->name == str) { if (hasProperty) *hasProperty = true; - return Node::create(v4, r->d()->list.at(ii)); + return Node::create(v4, r->d()->list().at(ii)); } } @@ -1588,7 +1595,7 @@ namespace Heap { struct QQmlXMLHttpRequestWrapper : Object { QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request); - ~QQmlXMLHttpRequestWrapper() { + void destroy() { delete request; } QQmlXMLHttpRequest *request; diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 1ca51ea360..02a5514275 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -76,7 +76,8 @@ struct QQmlDelegateModelGroupChange : Object { struct QQmlDelegateModelGroupChangeArray : Object { QQmlDelegateModelGroupChangeArray(const QVector &changes); - QVector changes; + void destroy() { delete changes; } + QVector *changes; }; @@ -1865,7 +1866,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject); -QV4::Heap::QQmlDelegateModelItemObject::~QQmlDelegateModelItemObject() +void QV4::Heap::QQmlDelegateModelItemObject::destroy() { item->Dispose(); } @@ -3256,8 +3257,8 @@ public: return engine->memoryManager->allocObject(changes); } - quint32 count() const { return d()->changes.count(); } - const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); } + quint32 count() const { return d()->changes->count(); } + const QQmlChangeSet::Change &at(int index) const { return d()->changes->at(index); } static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) { @@ -3300,7 +3301,7 @@ public: }; QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector &changes) - : changes(changes) + : changes(new QVector(changes)) { QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index bf9fd99f19..a34450ebd6 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -161,7 +161,7 @@ namespace QV4 { namespace Heap { struct QQmlDelegateModelItemObject : Object { inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item); - ~QQmlDelegateModelItemObject(); + void destroy(); QQmlDelegateModelItem *item; }; -- cgit v1.2.3 From 1b90dc4482d001512f09a5785d4cbd8030879d82 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 9 Sep 2016 10:43:08 +0200 Subject: QML: Make Heap::RegExp and Heap::String trivial Change-Id: Ia8eda67c9d59069d3a64363699720a79ba1348a1 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4function.cpp | 4 ++-- src/qml/jsruntime/qv4regexp.cpp | 15 +++++++++------ src/qml/jsruntime/qv4regexp_p.h | 15 ++++++++------- src/qml/jsruntime/qv4regexpobject.cpp | 4 ++-- src/qml/jsruntime/qv4runtime.cpp | 6 +++--- src/qml/jsruntime/qv4string.cpp | 8 ++++---- src/qml/jsruntime/qv4string_p.h | 5 +++-- src/qml/jsruntime/qv4stringobject.cpp | 2 +- src/qml/memory/qv4mm_p.h | 6 ++++-- 9 files changed, 36 insertions(+), 29 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 300e538d3d..caabee322a 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -73,7 +73,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, } // duplicate arguments, need some trick to store them MemoryManager *mm = engine->memoryManager; - arg = mm->alloc(mm, arg->d(), engine->newString(QString(0xfffe)), true); + arg = mm->alloc(mm, arg->d(), engine->newString(QString(0xfffe))); } } nFormals = compiledFunction->nFormals; @@ -105,7 +105,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QListmemoryManager->alloc(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)), true); + arg = engine->memoryManager->alloc(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe))); } } nFormals = parameters.size(); diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 7e2f4697c5..c2bc905ef5 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -66,7 +66,7 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) return uint(jitCode()->execute(s.characters16(), start, s.length(), (int*)matchOffsets).start); #endif - return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets); + return JSC::Yarr::interpret(byteCode(), s.characters16(), string.length(), start, matchOffsets); } Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline) @@ -90,19 +90,20 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo return result->d(); } -Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) - : pattern(pattern) - , ignoreCase(ignoreCase) - , multiLine(multiline) +void Heap::RegExp::init(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) { Base::init(); + this->pattern = new QString(pattern); + this->ignoreCase = ignoreCase; + this->multiLine = multiline; const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); if (error) return; subPatternCount = yarrPattern.m_numSubpatterns; - byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + OwnPtr p = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + byteCode = p.take(); #if ENABLE(YARR_JIT) jitCode = new JSC::Yarr::YarrCodeBlock; if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) { @@ -121,6 +122,8 @@ void Heap::RegExp::destroy() #if ENABLE(YARR_JIT) delete jitCode; #endif + delete byteCode; + delete pattern; } void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 33ed1d1117..b3bdeada94 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -76,11 +76,11 @@ struct RegExpCacheKey; namespace Heap { struct RegExp : Base { - RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); + void init(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); void destroy(); - QString pattern; - OwnPtr byteCode; + QString *pattern; + JSC::Yarr::BytecodePattern *byteCode; #if ENABLE(YARR_JIT) JSC::Yarr::YarrCodeBlock *jitCode; #endif @@ -91,6 +91,7 @@ struct RegExp : Base { int captureCount() const { return subPatternCount + 1; } }; +Q_STATIC_ASSERT(std::is_trivial::value); } @@ -100,8 +101,8 @@ struct RegExp : public Managed Q_MANAGED_TYPE(RegExp) V4_NEEDS_DESTROY - QString pattern() const { return d()->pattern; } - OwnPtr &byteCode() { return d()->byteCode; } + QString pattern() const { return *d()->pattern; } + JSC::Yarr::BytecodePattern *byteCode() { return d()->byteCode; } #if ENABLE(YARR_JIT) JSC::Yarr::YarrCodeBlock *jitCode() const { return d()->jitCode; } #endif @@ -112,7 +113,7 @@ struct RegExp : public Managed static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); - bool isValid() const { return d()->byteCode.get(); } + bool isValid() const { return d()->byteCode; } uint match(const QString& string, int start, uint *matchOffsets); @@ -143,7 +144,7 @@ struct RegExpCacheKey }; inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re) - : pattern(re->pattern) + : pattern(*re->pattern) , ignoreCase(re->ignoreCase) , multiLine(re->multiLine) {} diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 203def0bcf..b8780b8c53 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -145,7 +145,7 @@ void RegExpObject::initProperties() Q_ASSERT(value()); - QString p = value()->pattern; + QString p = *value()->pattern; if (p.isEmpty()) { p = QStringLiteral("(?:)"); } else { @@ -180,7 +180,7 @@ Value *RegExpObject::lastIndexProperty() QRegExp RegExpObject::toQRegExp() const { Qt::CaseSensitivity caseSensitivity = value()->ignoreCase ? Qt::CaseInsensitive : Qt::CaseSensitive; - return QRegExp(value()->pattern, caseSensitivity, QRegExp::RegExp2); + return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2); } QString RegExpObject::toString() const diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index e65f4118fb..0a71f0000a 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -555,7 +555,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue(); + return (mm->alloc(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } double x = RuntimeHelpers::toNumber(pleft); double y = RuntimeHelpers::toNumber(pright); @@ -572,7 +572,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu if (!right.stringValue()->d()->length()) return left.asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc(mm, left.stringValue()->d(), right.stringValue()->d(), true))->asReturnedValue(); + return (mm->alloc(mm, left.stringValue()->d(), right.stringValue()->d()))->asReturnedValue(); } Scope scope(engine); @@ -590,7 +590,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue(); + return (mm->alloc(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 8bc867e2cd..3365ffe637 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -74,10 +74,10 @@ bool String::isEqualTo(Managed *t, Managed *o) } -Heap::String::String(MemoryManager *mm, const QString &t) - : mm(mm) +void Heap::String::init(MemoryManager *mm, const QString &t) { Base::init(); + this->mm = mm; subtype = String::StringType_Unknown; @@ -89,10 +89,10 @@ Heap::String::String(MemoryManager *mm, const QString &t) len = text->size; } -Heap::String::String(MemoryManager *mm, String *l, String *r, bool) // TODO: remove the dummy bool when String is trivial - : mm(mm) +void Heap::String::init(MemoryManager *mm, String *l, String *r) { Base::init(); + this->mm = mm; subtype = String::StringType_Unknown; diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 50b7fb664a..40c5c8a263 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -71,8 +71,8 @@ struct Q_QML_PRIVATE_EXPORT String : Base { }; #ifndef V4_BOOTSTRAP - String(MemoryManager *mm, const QString &text); - String(MemoryManager *mm, String *l, String *n, bool dummy); + void init(MemoryManager *mm, const QString &text); + void init(MemoryManager *mm, String *l, String *n); void destroy() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); @@ -133,6 +133,7 @@ private: static void append(const String *data, QChar *ch); #endif }; +Q_STATIC_ASSERT(std::is_trivial::value); } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 1989f747e9..1c474fb18d 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -715,7 +715,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) Scoped re(scope, separatorValue); if (re) { - if (re->value()->pattern.isEmpty()) { + if (re->value()->pattern->isEmpty()) { re = (RegExpObject *)0; separatorValue = ctx->d()->engine->newString(); } diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 43cedbc165..cfd348e14a 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -142,9 +142,10 @@ public: template typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data), unmanagedSize)); - (void)new (t->d()) typename ManagedType::Data(this, arg1); + t->d_unchecked()->init(this, arg1); return t->d(); } @@ -296,9 +297,10 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { + Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4); + t->d_unchecked()->init(arg1, arg2, arg3, arg4); return t->d(); } -- cgit v1.2.3 From 59e48836e207aff52b2727cc4f3733209475e8bb Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Tue, 2 Aug 2016 13:25:35 +0200 Subject: Use QElapsedTimer instead of QTime to measure elapsed time Getting the current time from QTime is expensive as it adheres to the locale timezone. To measure elapsed time in a code block, using the monotonic QElapsedTimer is much faster. Change-Id: Ibea390d7bc5270a20cf35111dfc919e37be7001e Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/qml') diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 4592dd5c9b..2588d8db00 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -40,7 +40,7 @@ #include "PageAllocation.h" #include "StdLibExtras.h" -#include +#include #include #include @@ -562,18 +562,17 @@ void MemoryManager::runGC() } else { const size_t totalMem = getAllocatedMem(); - QTime t; + QElapsedTimer t; t.start(); mark(); - int markTime = t.elapsed(); - t.restart(); + qint64 markTime = t.restart(); const size_t usedBefore = getUsedMem(); const size_t largeItemsBefore = getLargeItemsMem(); int chunksBefore = m_d->heapChunks.size(); sweep(); const size_t usedAfter = getUsedMem(); const size_t largeItemsAfter = getLargeItemsMem(); - int sweepTime = t.elapsed(); + qint64 sweepTime = t.elapsed(); qDebug() << "========== GC =========="; qDebug() << "Marked object in" << markTime << "ms."; -- cgit v1.2.3 From 4a22a3b83be91cf781a049a7d9cb277950e5919f Mon Sep 17 00:00:00 2001 From: Frederik Schwarzer Date: Thu, 6 Oct 2016 10:46:54 +0200 Subject: Fix some minor issues in documentation Change-Id: I19f1a75b2e1a1096077df7ea109fd70be9d3c759 Reviewed-by: Shawn Rutledge --- src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index b136a0e92f..10c2819097 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -191,7 +191,7 @@ which was then imported by the client), then a property of type \section3 Assigning Values to Property Attributes -The value of a property of an object instance may specified in two separate ways: +The value of a property of an object instance may be specified in two separate ways: \list \li a value assignment on initialization \li an imperative value assignment -- cgit v1.2.3 From 738936361952b62f1ee7ee171c6400e0963853f6 Mon Sep 17 00:00:00 2001 From: Frederik Schwarzer Date: Thu, 25 Aug 2016 16:53:27 +0200 Subject: QDoc: fix several typos an minor wording issues in documentation Change-Id: Ie8cbcc27e0cbe2b9caa9a1adf24f056dafa203ed Reviewed-by: Shawn Rutledge --- src/qml/doc/src/cppclasses/topic.qdoc | 4 ++-- src/qml/doc/src/cppintegration/exposecppattributes.qdoc | 2 +- src/qml/doc/src/qmllanguageref/documents/scope.qdoc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/qml') diff --git a/src/qml/doc/src/cppclasses/topic.qdoc b/src/qml/doc/src/cppclasses/topic.qdoc index ddb29fbb14..133f9bc72c 100644 --- a/src/qml/doc/src/cppclasses/topic.qdoc +++ b/src/qml/doc/src/cppclasses/topic.qdoc @@ -91,7 +91,7 @@ at run-time using a QQmlComponent. An instance of the QQmlComponent class can be created in C++ directly, or via the \l{QtQml::Qt::createComponent()} {Qt.createComponent()} function in imperative QML code. Arbitrary expressions can be calculated in C++ via the QQmlExpression class, and such expressions -can interact directly the QML context. +can interact directly with the QML context. \section2 The QQmlComponent Class @@ -106,7 +106,7 @@ how to use QQmlComponent. The QQmlExpression class provides a way for clients to evaluate JavaScript expressions from C++, using a particular QML evaluation context. This allows -clients to access QML objects by id, for example. The result of evaluation +clients to access QML objects by id, for example. The result of the evaluation is returned as a QVariant, and the conversion rules are defined by the QML engine. diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc index f5aea0b01a..ed0d049564 100644 --- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc +++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc @@ -71,7 +71,7 @@ type that is supported by the QML engine. By default, the engine supports a number of Qt C++ types and can automatically convert them as appropriately when used from QML. Additionally, C++ classes that are \l{Registering C++ types with the QML type system}{registered} with -the QML type system can be can be used as data types, as can their enums if +the QML type system can be used as data types, as can their enums if appropriately registered. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++} for further information. diff --git a/src/qml/doc/src/qmllanguageref/documents/scope.qdoc b/src/qml/doc/src/qmllanguageref/documents/scope.qdoc index 3e3bbaca98..eaf1747a6d 100644 --- a/src/qml/doc/src/qmllanguageref/documents/scope.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/scope.qdoc @@ -105,7 +105,7 @@ ListView { \section1 Binding Scope Object -An object which has a \l{Property Binding}{property binding} is known has the +An object which has a \l{Property Binding}{property binding} is known as the binding's \e{scope object}. In the following example, the \l Item object is the binding's scope object. -- cgit v1.2.3 From 3b14e2ffdd8eb4b7f7f4508768b75f2acc399370 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 9 Sep 2016 15:37:57 +0200 Subject: QML: Make Heap::Object and all subclasses trivial GCC6 might dead-store-eliminate out our secret write to Base::mmdata, because it expects all memory content to be "undefined" before constructor calls. Clang might take the same approach if the constructor of Heap::Object is removed. By making these structs trivial, it also makes them memcpy-able. Change-Id: I055b2ad28311b997fbe059849ebda4d5894eaa9b Reviewed-by: Simon Hausmann --- src/qml/jsapi/qjsvalueiterator.cpp | 10 ++--- src/qml/jsruntime/qv4argumentsobject.cpp | 5 ++- src/qml/jsruntime/qv4argumentsobject_p.h | 22 +++++----- src/qml/jsruntime/qv4arraybuffer.cpp | 12 +++--- src/qml/jsruntime/qv4arraybuffer_p.h | 6 +-- src/qml/jsruntime/qv4arraydata_p.h | 4 +- src/qml/jsruntime/qv4arrayobject.cpp | 4 +- src/qml/jsruntime/qv4arrayobject_p.h | 2 +- src/qml/jsruntime/qv4booleanobject.cpp | 4 +- src/qml/jsruntime/qv4booleanobject_p.h | 2 +- src/qml/jsruntime/qv4context_p.h | 10 ++--- src/qml/jsruntime/qv4dataview.cpp | 4 +- src/qml/jsruntime/qv4dataview_p.h | 4 +- src/qml/jsruntime/qv4dateobject.cpp | 10 +++-- src/qml/jsruntime/qv4dateobject_p.h | 14 +++--- src/qml/jsruntime/qv4errorobject.cpp | 73 +++++++++++++++++--------------- src/qml/jsruntime/qv4errorobject_p.h | 38 ++++++++--------- src/qml/jsruntime/qv4functionobject.cpp | 63 +++++++++++++++------------ src/qml/jsruntime/qv4functionobject_p.h | 38 ++++++++--------- src/qml/jsruntime/qv4globalobject.cpp | 4 +- src/qml/jsruntime/qv4globalobject_p.h | 2 +- src/qml/jsruntime/qv4jsonobject.cpp | 3 +- src/qml/jsruntime/qv4jsonobject_p.h | 2 +- src/qml/jsruntime/qv4managed_p.h | 5 ++- src/qml/jsruntime/qv4mathobject.cpp | 3 +- src/qml/jsruntime/qv4mathobject_p.h | 2 +- src/qml/jsruntime/qv4memberdata_p.h | 2 +- src/qml/jsruntime/qv4numberobject.cpp | 4 +- src/qml/jsruntime/qv4numberobject_p.h | 2 +- src/qml/jsruntime/qv4object.cpp | 6 +-- src/qml/jsruntime/qv4object_p.h | 45 ++++++++++++-------- src/qml/jsruntime/qv4objectiterator.cpp | 24 ----------- src/qml/jsruntime/qv4objectiterator_p.h | 51 ++++++++++++++++++---- src/qml/jsruntime/qv4objectproto.cpp | 4 +- src/qml/jsruntime/qv4objectproto_p.h | 2 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 42 +++++++++--------- src/qml/jsruntime/qv4qobjectwrapper_p.h | 24 ++++++++--- src/qml/jsruntime/qv4regexp_p.h | 2 +- src/qml/jsruntime/qv4regexpobject.cpp | 15 ++++--- src/qml/jsruntime/qv4regexpobject_p.h | 8 ++-- src/qml/jsruntime/qv4script.cpp | 7 +-- src/qml/jsruntime/qv4sequenceobject.cpp | 22 +++++----- src/qml/jsruntime/qv4string_p.h | 2 +- src/qml/jsruntime/qv4stringobject.cpp | 10 +++-- src/qml/jsruntime/qv4stringobject_p.h | 6 +-- src/qml/jsruntime/qv4typedarray.cpp | 13 +++--- src/qml/jsruntime/qv4typedarray_p.h | 13 +++--- src/qml/jsruntime/qv4value_p.h | 2 +- src/qml/jsruntime/qv4variantobject.cpp | 6 ++- src/qml/jsruntime/qv4variantobject_p.h | 4 +- src/qml/memory/qv4heap_p.h | 20 +++++++-- src/qml/memory/qv4mm_p.h | 40 ++++++++--------- src/qml/qml/qqmlcomponent.cpp | 9 ++-- src/qml/qml/qqmlcontextwrapper.cpp | 9 ++-- src/qml/qml/qqmlcontextwrapper_p.h | 2 +- src/qml/qml/qqmllistwrapper.cpp | 21 ++++----- src/qml/qml/qqmllistwrapper_p.h | 11 ++++- src/qml/qml/qqmllocale_p.h | 2 +- src/qml/qml/qqmltypewrapper.cpp | 5 ++- src/qml/qml/qqmltypewrapper_p.h | 2 +- src/qml/qml/qqmlvaluetypewrapper.cpp | 39 ++++++++--------- src/qml/qml/qqmlvaluetypewrapper_p.h | 18 ++++++-- src/qml/qml/qqmlxmlhttprequest.cpp | 43 ++++++++++--------- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 21 +++++---- src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 15 ++++--- src/qml/types/qqmldelegatemodel.cpp | 28 ++++++------ src/qml/types/qqmldelegatemodel_p_p.h | 7 +-- src/qml/types/qqmllistmodel_p_p.h | 12 +++--- src/qml/util/qqmlchangeset_p.h | 25 ++++++++--- 69 files changed, 558 insertions(+), 433 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp index 86c7554924..ce472ce7e5 100644 --- a/src/qml/jsapi/qjsvalueiterator.cpp +++ b/src/qml/jsapi/qjsvalueiterator.cpp @@ -103,11 +103,11 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object) return; QV4::Scope scope(v4); QV4::Scoped it(scope, d_ptr->iterator.value()); - it->d()->it.flags = QV4::ObjectIterator::NoFlags; + it->d()->it().flags = QV4::ObjectIterator::NoFlags; QV4::ScopedString nm(scope); QV4::Property nextProperty; QV4::PropertyAttributes nextAttributes; - it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); + it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); d_ptr->nextName.set(v4, nm.asReturnedValue()); } @@ -157,7 +157,7 @@ bool QJSValueIterator::next() QV4::ScopedString nm(scope); QV4::Property nextProperty; QV4::PropertyAttributes nextAttributes; - it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); + it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); d_ptr->nextName.set(v4, nm.asReturnedValue()); return d_ptr->currentName.as() || d_ptr->currentIndex != UINT_MAX; } @@ -231,11 +231,11 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object) QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&object)); d_ptr->iterator.set(v4, v4->newForEachIteratorObject(o)); QV4::Scoped it(scope, d_ptr->iterator.value()); - it->d()->it.flags = QV4::ObjectIterator::NoFlags; + it->d()->it().flags = QV4::ObjectIterator::NoFlags; QV4::ScopedString nm(scope); QV4::Property nextProperty; QV4::PropertyAttributes nextAttributes; - it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); + it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); d_ptr->nextName.set(v4, nm.asReturnedValue()); return *this; } diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 156c21ca66..0dfdf25158 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -45,9 +45,10 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArgumentsObject); -Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context) - : fullyCreated(false) +void Heap::ArgumentsObject::init(QV4::CallContext *context) { + Object::init(); + fullyCreated = false; this->context = context->d(); Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable()); diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 6ccfd89fd4..37a8d0a94a 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -60,12 +60,12 @@ namespace QV4 { namespace Heap { struct ArgumentsGetterFunction : FunctionObject { - inline ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index); + inline void init(QV4::ExecutionContext *scope, uint index); uint index; }; struct ArgumentsSetterFunction : FunctionObject { - inline ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index); + inline void init(QV4::ExecutionContext *scope, uint index); uint index; }; @@ -75,7 +75,7 @@ struct ArgumentsObject : Object { CalleePropertyIndex = 1, CallerPropertyIndex = 3 }; - ArgumentsObject(QV4::CallContext *context); + void init(QV4::CallContext *context); Pointer context; bool fullyCreated; Pointer mappedArguments; @@ -91,11 +91,11 @@ struct ArgumentsGetterFunction: FunctionObject static void call(const Managed *that, Scope &scope, CallData *d); }; -inline -Heap::ArgumentsGetterFunction::ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index) - : Heap::FunctionObject(scope) - , index(index) +inline void +Heap::ArgumentsGetterFunction::init(QV4::ExecutionContext *scope, uint index) { + Heap::FunctionObject::init(scope); + this->index = index; } struct ArgumentsSetterFunction: FunctionObject @@ -106,11 +106,11 @@ struct ArgumentsSetterFunction: FunctionObject static void call(const Managed *that, Scope &scope, CallData *callData); }; -inline -Heap::ArgumentsSetterFunction::ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index) - : Heap::FunctionObject(scope) - , index(index) +inline void +Heap::ArgumentsSetterFunction::init(QV4::ExecutionContext *scope, uint index) { + Heap::FunctionObject::init(scope); + this->index = index; } diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index e88f17a658..908fa52680 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -46,9 +46,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArrayBufferCtor); DEFINE_OBJECT_VTABLE(ArrayBuffer); -Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("ArrayBuffer")) +void Heap::ArrayBufferCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("ArrayBuffer")); } void ArrayBufferCtor::construct(const Managed *m, Scope &scope, CallData *callData) @@ -94,8 +94,9 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx) } -Heap::ArrayBuffer::ArrayBuffer(size_t length) +void Heap::ArrayBuffer::init(size_t length) { + Object::init(); data = QTypedArrayData::allocate(length + 1); if (!data) { data = 0; @@ -106,9 +107,10 @@ Heap::ArrayBuffer::ArrayBuffer(size_t length) memset(data->data(), 0, length + 1); } -Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array) - : data(const_cast(array).data_ptr()) +void Heap::ArrayBuffer::init(const QByteArray& array) { + Object::init(); + data = const_cast(array).data_ptr(); data->ref.ref(); } diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index a5ca0f6bad..bc56d1ea31 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -60,12 +60,12 @@ namespace QV4 { namespace Heap { struct ArrayBufferCtor : FunctionObject { - ArrayBufferCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object { - ArrayBuffer(size_t length); - ArrayBuffer(const QByteArray& array); + void init(size_t length); + void init(const QByteArray& array); void destroy(); QTypedArrayData *data; diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index ba0cc7cb30..9f810a32d5 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -133,7 +133,7 @@ struct ArrayData : public Base { } }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(ArrayData) struct SimpleArrayData : public ArrayData { uint mappedIndex(uint index) const { return (index + offset) % alloc; } @@ -153,7 +153,7 @@ struct SimpleArrayData : public ArrayData { return attrs ? attrs[i] : Attr_Data; } }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(SimpleArrayData) struct SparseArrayData : public ArrayData { void destroy() { delete sparse; } diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 4d15c6c137..76faef137f 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -49,9 +49,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArrayCtor); -Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Array")) +void Heap::ArrayCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Array")); } void ArrayCtor::construct(const Managed *m, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index f49ed76b02..9a05bb8681 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct ArrayCtor : FunctionObject { - ArrayCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 57c54e15c4..8047993266 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -45,9 +45,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(BooleanCtor); DEFINE_OBJECT_VTABLE(BooleanObject); -Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Boolean")) +void Heap::BooleanCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Boolean")); } void BooleanCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 17543e33e0..4c2f3c09e7 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct BooleanCtor : FunctionObject { - BooleanCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index ffedf737ce..0b42288ccc 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -128,7 +128,7 @@ struct ExecutionContext : Base { bool strictMode : 8; int lineNumber; }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(ExecutionContext) struct CallContext : ExecutionContext { static CallContext createOnStack(ExecutionEngine *v4); @@ -145,20 +145,20 @@ struct CallContext : ExecutionContext { Value *locals; Pointer activation; }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(CallContext) struct GlobalContext : ExecutionContext { void init(ExecutionEngine *engine); Pointer global; }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(GlobalContext) struct CatchContext : ExecutionContext { void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue); Pointer exceptionVarName; Value exceptionValue; }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(CatchContext) struct WithContext : ExecutionContext { void init(ExecutionContext *outerContext, Object *with) @@ -175,7 +175,7 @@ struct WithContext : ExecutionContext { Pointer withObject; }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(WithContext) struct QmlContextWrapper; diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index fac3d5316c..db8376272d 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -49,9 +49,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(DataViewCtor); DEFINE_OBJECT_VTABLE(DataView); -Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("DataView")) +void Heap::DataViewCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("DataView")); } void DataViewCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h index f996a4c2f1..246124394a 100644 --- a/src/qml/jsruntime/qv4dataview_p.h +++ b/src/qml/jsruntime/qv4dataview_p.h @@ -60,11 +60,11 @@ namespace QV4 { namespace Heap { struct DataViewCtor : FunctionObject { - DataViewCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct DataView : Object { - DataView() {} + void init() { Object::init(); } Pointer buffer; uint byteLength; uint byteOffset; diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 04358fe3b5..4f3138a452 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -634,13 +634,15 @@ static double getLocalTZA() DEFINE_OBJECT_VTABLE(DateObject); -Heap::DateObject::DateObject(const QDateTime &date) +void Heap::DateObject::init(const QDateTime &date) { + Object::init(); this->date = date.isValid() ? date.toMSecsSinceEpoch() : qt_qnan(); } -Heap::DateObject::DateObject(const QTime &time) +void Heap::DateObject::init(const QTime &time) { + Object::init(); if (!time.isValid()) { date = qt_qnan(); return; @@ -668,9 +670,9 @@ QDateTime DateObject::toQDateTime() const DEFINE_OBJECT_VTABLE(DateCtor); -Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Date")) +void Heap::DateCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Date")); } void DateCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index c67acdcfa2..2d0648396e 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -63,24 +63,26 @@ namespace QV4 { namespace Heap { struct DateObject : Object { - DateObject() + void init() { + Object::init(); date = qt_qnan(); } - DateObject(const Value &date) + void init(const Value &date) { + Object::init(); this->date = date.toNumber(); } - DateObject(const QDateTime &date); - double date; + void init(const QDateTime &date); + void init(const QTime &time); - DateObject(const QTime &time); + double date; }; struct DateCtor : FunctionObject { - DateCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index bb5d32cbd7..597ded6ae1 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -67,8 +67,9 @@ using namespace QV4; -Heap::ErrorObject::ErrorObject() +void Heap::ErrorObject::init() { + Object::init(); stackTrace = nullptr; Scope scope(internalClass->engine); @@ -83,8 +84,9 @@ Heap::ErrorObject::ErrorObject() *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined(); } -Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t) +void Heap::ErrorObject::init(const Value &message, ErrorType t) { + Object::init(); errorType = t; Scope scope(internalClass->engine); @@ -103,8 +105,9 @@ Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t) *propertyData(QV4::ErrorObject::Index_Message) = message; } -Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) +void Heap::ErrorObject::init(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) { + Object::init(); errorType = t; Scope scope(internalClass->engine); @@ -183,44 +186,44 @@ DEFINE_OBJECT_VTABLE(ErrorObject); DEFINE_OBJECT_VTABLE(SyntaxErrorObject); -Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg) - : Heap::ErrorObject(msg, SyntaxError) +void Heap::SyntaxErrorObject::init(const Value &msg) { + Heap::ErrorObject::init(msg, SyntaxError); } -Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, SyntaxError) +void Heap::SyntaxErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) { + Heap::ErrorObject::init(msg, fileName, lineNumber, columnNumber, SyntaxError); } -Heap::EvalErrorObject::EvalErrorObject(const Value &message) - : Heap::ErrorObject(message, EvalError) +void Heap::EvalErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, EvalError); } -Heap::RangeErrorObject::RangeErrorObject(const Value &message) - : Heap::ErrorObject(message, RangeError) +void Heap::RangeErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, RangeError); } -Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &message) - : Heap::ErrorObject(message, ReferenceError) +void Heap::ReferenceErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, ReferenceError); } -Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, ReferenceError) +void Heap::ReferenceErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) { + Heap::ErrorObject::init(msg, fileName, lineNumber, columnNumber, ReferenceError); } -Heap::TypeErrorObject::TypeErrorObject(const Value &message) - : Heap::ErrorObject(message, TypeError) +void Heap::TypeErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, TypeError); } -Heap::URIErrorObject::URIErrorObject(const Value &message) - : Heap::ErrorObject(message, URIError) +void Heap::URIErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, URIError); } DEFINE_OBJECT_VTABLE(ErrorCtor); @@ -231,14 +234,14 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor); DEFINE_OBJECT_VTABLE(TypeErrorCtor); DEFINE_OBJECT_VTABLE(URIErrorCtor); -Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Error")) +void Heap::ErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Error")); } -Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name) - : Heap::FunctionObject(scope, name) +void Heap::ErrorCtor::init(QV4::ExecutionContext *scope, const QString &name) { + Heap::FunctionObject::init(scope, name); } void ErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -252,9 +255,9 @@ void ErrorCtor::call(const Managed *that, Scope &scope, CallData *callData) static_cast(that)->construct(scope, callData); } -Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("EvalError")) +void Heap::EvalErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("EvalError")); } void EvalErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -263,9 +266,9 @@ void EvalErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) scope.result = ErrorObject::create(scope.engine, v); } -Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("RangeError")) +void Heap::RangeErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("RangeError")); } void RangeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -274,9 +277,9 @@ void RangeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData scope.result = ErrorObject::create(scope.engine, v); } -Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("ReferenceError")) +void Heap::ReferenceErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("ReferenceError")); } void ReferenceErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -285,9 +288,9 @@ void ReferenceErrorCtor::construct(const Managed *, Scope &scope, CallData *call scope.result = ErrorObject::create(scope.engine, v); } -Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("SyntaxError")) +void Heap::SyntaxErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("SyntaxError")); } void SyntaxErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -296,9 +299,9 @@ void SyntaxErrorCtor::construct(const Managed *, Scope &scope, CallData *callDat scope.result = ErrorObject::create(scope.engine, v); } -Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("TypeError")) +void Heap::TypeErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("TypeError")); } void TypeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -307,9 +310,9 @@ void TypeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) scope.result = ErrorObject::create(scope.engine, v); } -Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("URIError")) +void Heap::URIErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("URIError")); } void URIErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 206c7e6c59..b7a0889e08 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -73,9 +73,9 @@ struct ErrorObject : Object { URIError }; - ErrorObject(); - ErrorObject(const Value &message, ErrorType t = Error); - ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); + void init(); + void init(const Value &message, ErrorType t = Error); + void init(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); void destroy() { delete stackTrace; } ErrorType errorType; @@ -84,58 +84,58 @@ struct ErrorObject : Object { }; struct EvalErrorObject : ErrorObject { - EvalErrorObject(const Value &message); + void init(const Value &message); }; struct RangeErrorObject : ErrorObject { - RangeErrorObject(const Value &message); + void init(const Value &message); }; struct ReferenceErrorObject : ErrorObject { - ReferenceErrorObject(const Value &message); - ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); + void init(const Value &message); + void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); }; struct SyntaxErrorObject : ErrorObject { - SyntaxErrorObject(const Value &message); - SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); + void init(const Value &message); + void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); }; struct TypeErrorObject : ErrorObject { - TypeErrorObject(const Value &message); + void init(const Value &message); }; struct URIErrorObject : ErrorObject { - URIErrorObject(const Value &message); + void init(const Value &message); }; struct ErrorCtor : Heap::FunctionObject { - ErrorCtor(QV4::ExecutionContext *scope); - ErrorCtor(QV4::ExecutionContext *scope, const QString &name); + void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope, const QString &name); }; struct EvalErrorCtor : ErrorCtor { - EvalErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct RangeErrorCtor : ErrorCtor { - RangeErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct ReferenceErrorCtor : ErrorCtor { - ReferenceErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct SyntaxErrorCtor : ErrorCtor { - SyntaxErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct TypeErrorCtor : ErrorCtor { - TypeErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct URIErrorCtor : ErrorCtor { - URIErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index aa8c7d6a81..118ed89c43 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -68,18 +68,20 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope->engine()); ScopedFunctionObject f(s, this); f->init(name, createProto); } -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope->engine()); ScopedString name(s, function->name()); @@ -87,9 +89,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun f->init(name, createProto); } -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope->engine()); ScopedFunctionObject f(s, this); @@ -97,9 +100,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString f->init(n, createProto); } -Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(ExecutionContext *scope, const QString &name, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope; Scope s(scope->engine); ScopedFunctionObject f(s, this); @@ -107,9 +111,10 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam f->init(n, createProto); } -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const ReturnedValue name) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope); ScopedFunctionObject f(s, this); @@ -117,9 +122,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne f->init(n, false); } -Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(ExecutionContext *scope, const ReturnedValue name) { + Object::init(); + function = nullptr; this->scope = scope; Scope s(scope->engine); ScopedFunctionObject f(s, this); @@ -127,9 +133,10 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu f->init(n, false); } -Heap::FunctionObject::FunctionObject() - : function(Q_NULLPTR) +void Heap::FunctionObject::init() { + Object::init(); + function = nullptr; this->scope = internalClass->engine->rootContext()->d(); Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype); *propertyData(Index_Prototype) = Encode::undefined(); @@ -227,7 +234,7 @@ QQmlSourceLocation FunctionObject::sourceLocation() const { if (isBinding()) { Q_ASSERT(as()); - return static_cast(d())->bindingLocation; + return *static_cast(d())->bindingLocation; } QV4::Function *function = d()->function; Q_ASSERT(function); @@ -237,9 +244,9 @@ QQmlSourceLocation FunctionObject::sourceLocation() const DEFINE_OBJECT_VTABLE(FunctionCtor); -Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Function")) +void Heap::FunctionCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Function")); } // 15.3.2 @@ -305,8 +312,9 @@ void FunctionCtor::call(const Managed *that, Scope &scope, CallData *callData) DEFINE_OBJECT_VTABLE(FunctionPrototype); -Heap::FunctionPrototype::FunctionPrototype() +void Heap::FunctionPrototype::init() { + Heap::FunctionObject::init(); } void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) @@ -417,9 +425,9 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx) DEFINE_OBJECT_VTABLE(ScriptFunction); -Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *function) - : Heap::SimpleScriptFunction(scope, function, true) +void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) { + Heap::SimpleScriptFunction::init(scope, function, true); } void ScriptFunction::construct(const Managed *that, Scope &scope, CallData *callData) @@ -478,8 +486,9 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData) DEFINE_OBJECT_VTABLE(SimpleScriptFunction); -Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto) +void Heap::SimpleScriptFunction::init(QV4::ExecutionContext *scope, Function *function, bool createProto) { + FunctionObject::init(); this->scope = scope->d(); this->function = function; @@ -599,10 +608,10 @@ Heap::Object *SimpleScriptFunction::protoForConstructor() DEFINE_OBJECT_VTABLE(BuiltinFunction); -Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)) - : Heap::FunctionObject(scope, name) - , code(code) +void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)) { + Heap::FunctionObject::init(scope, name); + this->code = code; } void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *) @@ -656,10 +665,10 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); DEFINE_OBJECT_VTABLE(BoundFunction); -Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, - const Value &boundThis, QV4::MemberData *boundArgs) - : Heap::FunctionObject(scope, QStringLiteral("__bound function__")) +void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, + const Value &boundThis, QV4::MemberData *boundArgs) { + Heap::FunctionObject::init(scope, QStringLiteral("__bound function__")); this->target = target->d(); this->boundArgs = boundArgs ? boundArgs->d() : 0; this->boundThis = boundThis; diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index f5a9376b9e..e58b83e2c3 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -69,13 +69,13 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { Index_ProtoConstructor = 0 }; - FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false); - FunctionObject(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false); - FunctionObject(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false); - FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); - FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name); - FunctionObject(ExecutionContext *scope, const ReturnedValue name); - FunctionObject(); + void init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false); + void init(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false); + void init(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false); + void init(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); + void init(QV4::ExecutionContext *scope, const ReturnedValue name); + void init(ExecutionContext *scope, const ReturnedValue name); + void init(); void destroy(); unsigned int formalParameterCount() { return function ? function->nFormals : 0; } @@ -87,20 +87,20 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { }; struct FunctionCtor : FunctionObject { - FunctionCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct FunctionPrototype : FunctionObject { - FunctionPrototype(); + void init(); }; struct Q_QML_EXPORT BuiltinFunction : FunctionObject { - BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)); + void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)); ReturnedValue (*code)(QV4::CallContext *); }; struct IndexedBuiltinFunction : FunctionObject { - inline IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index)); + inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index)); ReturnedValue (*code)(QV4::CallContext *, uint index); uint index; }; @@ -110,15 +110,15 @@ struct SimpleScriptFunction : FunctionObject { Index_Name = FunctionObject::Index_Prototype + 1, Index_Length }; - SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto); + void init(QV4::ExecutionContext *scope, Function *function, bool createProto); }; struct ScriptFunction : SimpleScriptFunction { - ScriptFunction(QV4::ExecutionContext *scope, Function *function); + void init(QV4::ExecutionContext *scope, Function *function); }; struct BoundFunction : FunctionObject { - BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); + void init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); Pointer target; Value boundThis; Pointer boundArgs; @@ -216,12 +216,12 @@ struct IndexedBuiltinFunction: FunctionObject static void call(const Managed *that, Scope &scope, CallData *callData); }; -Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, - ReturnedValue (*code)(QV4::CallContext *ctx, uint index)) - : Heap::FunctionObject(scope), - code(code) - , index(index) +void Heap::IndexedBuiltinFunction::init(QV4::ExecutionContext *scope, uint index, + ReturnedValue (*code)(QV4::CallContext *ctx, uint index)) { + Heap::FunctionObject::init(scope); + this->index = index; + this->code = code; } diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index b88e271a26..feb0d90d26 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -330,9 +330,9 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok) DEFINE_OBJECT_VTABLE(EvalFunction); -Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, scope->d()->engine->id_eval()) +void Heap::EvalFunction::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, scope->d()->engine->id_eval()); Scope s(scope); ScopedFunctionObject f(s, this); f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1)); diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 403639f8c1..e8b3a92d34 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -60,7 +60,7 @@ namespace QV4 { namespace Heap { struct EvalFunction : FunctionObject { - EvalFunction(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 5b665d8836..9636fefc14 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -867,8 +867,9 @@ QString Stringify::JA(ArrayObject *a) } -Heap::JsonObject::JsonObject() +void Heap::JsonObject::init() { + Object::init(); Scope scope(internalClass->engine); ScopedObject o(scope, this); diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index c3a3b191c0..43248a214d 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -64,7 +64,7 @@ namespace QV4 { namespace Heap { struct JsonObject : Object { - JsonObject(); + void init(); }; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index b56155b5db..0359559f34 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -88,9 +88,10 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} QV4::Heap::DataClass *d_unchecked() const { return static_cast(m()); } \ QV4::Heap::DataClass *d() const { \ QV4::Heap::DataClass *dptr = d_unchecked(); \ - if (std::is_trivial::value) dptr->_checkIsInitialized(); \ + dptr->_checkIsInitialized(); \ return dptr; \ - } + } \ + V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass) #define V4_MANAGED(DataClass, superClass) \ private: \ diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 9fe8224736..e03b2762cc 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -51,8 +51,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(MathObject); -Heap::MathObject::MathObject() +void Heap::MathObject::init() { + Object::init(); Scope scope(internalClass->engine); ScopedObject m(scope, this); diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index 01e778d9ec..f6b1a4395f 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -59,7 +59,7 @@ namespace QV4 { namespace Heap { struct MathObject : Object { - MathObject(); + void init(); }; } diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index 41da730428..969eee3619 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -66,7 +66,7 @@ struct MemberData : Base { }; Value data[1]; }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(MemberData) } diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index f8e0d8763b..1733df34ae 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -71,9 +71,9 @@ const NumberLocale *NumberLocale::instance() return numberLocaleHolder(); } -Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Number")) +void Heap::NumberCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Number")); } void NumberCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 2416165c78..6022b3a029 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct NumberCtor : FunctionObject { - NumberCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index aeb185049f..00e6d230da 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1160,10 +1160,10 @@ void Object::initSparseArray() DEFINE_OBJECT_VTABLE(ArrayObject); -Heap::ArrayObject::ArrayObject(const QStringList &list) - : Heap::Object() +void Heap::ArrayObject::init(const QStringList &list) { - init(); + Object::init(); + commonInit(); Scope scope(internalClass->engine); ScopedObject a(scope, this); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 54ce2ea60d..6ddeb84d3c 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -68,7 +68,7 @@ namespace QV4 { namespace Heap { struct Object : Base { - inline Object() { Base::init(); } + void init() { Base::init(); } const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } @@ -93,9 +93,10 @@ struct Object : Base { Data *d_unchecked() const { return static_cast(m()); } \ Data *d() const { \ Data *dptr = d_unchecked(); \ - if (std::is_trivial::value) dptr->_checkIsInitialized(); \ + dptr->_checkIsInitialized(); \ return dptr; \ - } + } \ + V4_ASSERT_IS_TRIVIAL(Data); #define V4_OBJECT2(DataClass, superClass) \ private: \ @@ -111,9 +112,10 @@ struct Object : Base { QV4::Heap::DataClass *d_unchecked() const { return static_cast(m()); } \ QV4::Heap::DataClass *d() const { \ QV4::Heap::DataClass *dptr = d_unchecked(); \ - if (std::is_trivial::value) dptr->_checkIsInitialized(); \ + dptr->_checkIsInitialized(); \ return dptr; \ - } + } \ + V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass); #define V4_INTERNALCLASS(c) \ static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \ @@ -375,18 +377,22 @@ private: namespace Heap { struct BooleanObject : Object { - BooleanObject() {} - BooleanObject(bool b) - : b(b) - {} + void init() { Object::init(); } + void init(bool b) { + Object::init(); + this->b = b; + } + bool b; }; struct NumberObject : Object { - NumberObject() {} - NumberObject(double val) - : value(val) - {} + void init() { Object::init(); } + void init(double val) { + Object::init(); + value = val; + } + double value; }; @@ -395,10 +401,15 @@ struct ArrayObject : Object { LengthPropertyIndex = 0 }; - ArrayObject() - { init(); } - ArrayObject(const QStringList &list); - void init() + void init() { + Object::init(); + commonInit(); + } + + void init(const QStringList &list); + +private: + void commonInit() { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); } }; diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index 4354e09248..7943a13ac0 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -45,30 +45,6 @@ using namespace QV4; -ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags) - : engine(e) - , object(scratch1) - , current(scratch2) - , arrayNode(0) - , arrayIndex(0) - , memberIndex(0) - , flags(flags) -{ - init(o); -} - -ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags) - : engine(scope.engine) - , object(scope.alloc(1)) - , current(scope.alloc(1)) - , arrayNode(0) - , arrayIndex(0) - , memberIndex(0) - , flags(flags) -{ - init(o); -} - void ObjectIterator::init(const Object *o) { object->setM(o ? o->m() : 0); diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h index 6bef703a4d..98e94a95ea 100644 --- a/src/qml/jsruntime/qv4objectiterator_p.h +++ b/src/qml/jsruntime/qv4objectiterator_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct Q_QML_EXPORT ObjectIterator +struct Q_QML_EXPORT ObjectIteratorData { enum Flags { NoFlags = 0, @@ -72,21 +72,52 @@ struct Q_QML_EXPORT ObjectIterator uint arrayIndex; uint memberIndex; uint flags; +}; +V4_ASSERT_IS_TRIVIAL(ObjectIteratorData) + +struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData +{ + ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags) + { + engine = e; + object = scratch1; + current = scratch2; + arrayNode = nullptr; + arrayIndex = 0; + memberIndex = 0; + this->flags = flags; + init(o); + } + + ObjectIterator(Scope &scope, const Object *o, uint flags) + { + engine = scope.engine; + object = scope.alloc(1); + current = scope.alloc(1); + arrayNode = nullptr; + arrayIndex = 0; + memberIndex = 0; + this->flags = flags; + init(o); + } - ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags); - ObjectIterator(Scope &scope, const Object *o, uint flags); - void init(const Object *o); void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0); ReturnedValue nextPropertyName(Value *value); ReturnedValue nextPropertyNameAsString(Value *value); ReturnedValue nextPropertyNameAsString(); + +private: + void init(const Object *o); }; namespace Heap { struct ForEachIteratorObject : Object { - ForEachIteratorObject(QV4::Object *o); - ObjectIterator it; + void init(QV4::Object *o); + ObjectIterator &it() { return *reinterpret_cast(&itData); } Value workArea[2]; + +private: + ObjectIteratorData itData; }; } @@ -95,16 +126,18 @@ struct ForEachIteratorObject: Object { V4_OBJECT2(ForEachIteratorObject, Object) Q_MANAGED_TYPE(ForeachIteratorObject) - ReturnedValue nextPropertyName() { return d()->it.nextPropertyNameAsString(); } + ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); } protected: static void markObjects(Heap::Base *that, ExecutionEngine *e); }; inline -Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::Object *o) - : it(internalClass->engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) +void Heap::ForEachIteratorObject::init(QV4::Object *o) { + Object::init(); + it() = ObjectIterator(internalClass->engine, workArea, workArea + 1, o, + ObjectIterator::EnumerableOnly | ObjectIterator::WithProtoChain); } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index cfd76166f2..6020c48250 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -54,9 +54,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ObjectCtor); -Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Object")) +void Heap::ObjectCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Object")); } void ObjectCtor::construct(const Managed *that, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index 47a37b196f..e3d85782d5 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct ObjectCtor : FunctionObject { - ObjectCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index c977573b9b..fc3d147c1d 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -195,8 +195,9 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object } } -Heap::QObjectWrapper::QObjectWrapper(QObject *object) +void Heap::QObjectWrapper::init(QObject *object) { + Object::init(); qObj.init(object); } @@ -1680,7 +1681,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in method->d()->setObject(object); if (QQmlData *ddata = QQmlData::get(object)) - method->d()->propertyCache = ddata->propertyCache; + method->d()->setPropertyCache(ddata->propertyCache); method->d()->index = index; return method.asReturnedValue(); @@ -1690,21 +1691,21 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueType { Scope valueScope(scope); Scoped method(valueScope, valueScope.engine->memoryManager->allocObject(scope)); - method->d()->propertyCache = valueType->d()->propertyCache; + method->d()->setPropertyCache(valueType->d()->propertyCache()); method->d()->index = index; method->d()->valueTypeWrapper = valueType->d(); return method.asReturnedValue(); } -Heap::QObjectMethod::QObjectMethod(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope) +void Heap::QObjectMethod::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope); } const QMetaObject *Heap::QObjectMethod::metaObject() { - if (propertyCache) - return propertyCache->createMetaObject(); + if (propertyCache()) + return propertyCache()->createMetaObject(); return object()->metaObject(); } @@ -1776,13 +1777,13 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const return; } - object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr); + object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr); } QQmlPropertyData method; - if (d()->propertyCache) { - QQmlPropertyData *data = d()->propertyCache->method(d()->index); + if (d()->propertyCache()) { + QQmlPropertyData *data = d()->propertyCache()->method(d()->index); if (!data) { scope.result = QV4::Encode::undefined(); return; @@ -1825,7 +1826,7 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const if (!method.isOverload()) { scope.result = CallPrecise(object, method, v4, callData); } else { - scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache); + scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache()); } } @@ -1841,11 +1842,13 @@ void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e) DEFINE_OBJECT_VTABLE(QObjectMethod); -Heap::QMetaObjectWrapper::QMetaObjectWrapper(const QMetaObject *metaObject) - : metaObject(metaObject) - , constructors(nullptr) - , constructorCount(0) -{} +void Heap::QMetaObjectWrapper::init(const QMetaObject *metaObject) +{ + FunctionObject::init(); + this->metaObject = metaObject; + constructors = nullptr; + constructorCount = 0; +} void Heap::QMetaObjectWrapper::destroy() { @@ -2013,9 +2016,10 @@ DEFINE_OBJECT_VTABLE(QMetaObjectWrapper); -Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex) - : signalIndex(signalIndex) +void Heap::QmlSignalHandler::init(QObject *object, int signalIndex) { + Object::init(); + this->signalIndex = signalIndex; setObject(object); } @@ -2023,7 +2027,7 @@ DEFINE_OBJECT_VTABLE(QmlSignalHandler); void QmlSignalHandler::initProto(ExecutionEngine *engine) { - if (engine->signalHandlerPrototype()->d()) + if (engine->signalHandlerPrototype()->d_unchecked()) return; Scope scope(engine); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 37397db55b..727af6c9c6 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -78,7 +78,7 @@ namespace Heap { struct QQmlValueTypeWrapper; struct QObjectWrapper : Object { - QObjectWrapper(QObject *object); + void init(QObject *object); void destroy() { qObj.destroy(); } QObject *object() const { return qObj.data(); } @@ -88,16 +88,22 @@ private: }; struct QObjectMethod : FunctionObject { - QObjectMethod(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); void destroy() { - propertyCache = nullptr; + setPropertyCache(nullptr); qObj.destroy(); FunctionObject::destroy(); } - QQmlRefPointer propertyCache; - int index; + QQmlPropertyCache *propertyCache() const { return _propertyCache; } + void setPropertyCache(QQmlPropertyCache *c) { + if (c) + c->addref(); + if (_propertyCache) + _propertyCache->release(); + _propertyCache = c; + } Pointer valueTypeWrapper; @@ -107,6 +113,10 @@ struct QObjectMethod : FunctionObject { private: QQmlQPointer qObj; + QQmlPropertyCache *_propertyCache; + +public: + int index; }; struct QMetaObjectWrapper : FunctionObject { @@ -114,13 +124,13 @@ struct QMetaObjectWrapper : FunctionObject { QQmlPropertyData *constructors; int constructorCount; - QMetaObjectWrapper(const QMetaObject* metaObject); + void init(const QMetaObject* metaObject); void destroy(); void ensureConstructorsCache(); }; struct QmlSignalHandler : Object { - QmlSignalHandler(QObject *object, int signalIndex); + void init(QObject *object, int signalIndex); void destroy() { qObj.destroy(); } int signalIndex; diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index b3bdeada94..d3e63375a5 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -91,7 +91,7 @@ struct RegExp : Base { int captureCount() const { return subPatternCount + 1; } }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(RegExp) } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index b8780b8c53..4022d98c3f 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -69,8 +69,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(RegExpObject); -Heap::RegExpObject::RegExpObject() +void Heap::RegExpObject::init() { + Object::init(); Scope scope(internalClass->engine); Scoped o(scope, this); o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false); @@ -78,9 +79,10 @@ Heap::RegExpObject::RegExpObject() o->initProperties(); } -Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global) - : global(global) +void Heap::RegExpObject::init(QV4::RegExp *value, bool global) { + Object::init(); + this->global = global; this->value = value->d(); Scope scope(internalClass->engine); Scoped o(scope, this); @@ -90,8 +92,9 @@ Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global) // Converts a QRegExp to a JS RegExp. // The conversion is not 100% exact since ECMA regexp and QRegExp // have different semantics/flags, but we try to do our best. -Heap::RegExpObject::RegExpObject(const QRegExp &re) +void Heap::RegExpObject::init(const QRegExp &re) { + Object::init(); global = false; // Convert the pattern to a ECMAScript pattern. @@ -217,9 +220,9 @@ uint RegExpObject::flags() const DEFINE_OBJECT_VTABLE(RegExpCtor); -Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("RegExp")) +void Heap::RegExpCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("RegExp")); clearLastMatch(); } diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 655e120c16..2c82cfdfd1 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -74,16 +74,16 @@ namespace QV4 { namespace Heap { struct RegExpObject : Object { - RegExpObject(); - RegExpObject(QV4::RegExp *value, bool global); - RegExpObject(const QRegExp &re); + void init(); + void init(QV4::RegExp *value, bool global); + void init(const QRegExp &re); Pointer value; bool global; }; struct RegExpCtor : FunctionObject { - RegExpCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); Value lastMatch; Pointer lastInput; int lastMatchStart; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index e3475e5cd6..787047806a 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -65,7 +65,7 @@ namespace QV4 { namespace Heap { struct QmlBindingWrapper : FunctionObject { - QmlBindingWrapper(QV4::QmlContext *scope, Function *f); + void init(QV4::QmlContext *scope, Function *f); }; } @@ -84,9 +84,10 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlBindingWrapper); -Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f) - : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false) +void Heap::QmlBindingWrapper::init(QV4::QmlContext *scope, Function *f) { + Heap::FunctionObject::init(scope, scope->d()->engine->id_eval(), /*createProto = */ false); + Q_ASSERT(scope->inUse()); function = f; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index fb9ef4a2b2..4b82a7d83f 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -216,8 +216,8 @@ namespace Heap { template struct QQmlSequence : Object { - QQmlSequence(const Container &container); - QQmlSequence(QObject *object, int propertyIndex); + void init(const Container &container); + void init(QObject *object, int propertyIndex); void destroy() { delete container; object.destroy(); @@ -557,11 +557,12 @@ public: template -Heap::QQmlSequence::QQmlSequence(const Container &container) - : container(new Container(container)) - , propertyIndex(-1) - , isReference(false) +void Heap::QQmlSequence::init(const Container &container) { + Object::init(); + this->container = new Container(container); + propertyIndex = -1; + isReference = false; object.init(); QV4::Scope scope(internalClass->engine); @@ -571,11 +572,12 @@ Heap::QQmlSequence::QQmlSequence(const Container &container) } template -Heap::QQmlSequence::QQmlSequence(QObject *object, int propertyIndex) - : container(new Container) - , propertyIndex(propertyIndex) - , isReference(true) +void Heap::QQmlSequence::init(QObject *object, int propertyIndex) { + Object::init(); + this->container = new Container; + this->propertyIndex = propertyIndex; + isReference = true; this->object.init(object); QV4::Scope scope(internalClass->engine); QV4::Scoped > o(scope, this); diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 40c5c8a263..df34ec0151 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -133,7 +133,7 @@ private: static void append(const String *data, QChar *ch); #endif }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(String) } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 1c474fb18d..829ada0c1a 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -73,15 +73,17 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(StringObject); -Heap::StringObject::StringObject() +void Heap::StringObject::init() { + Object::init(); Q_ASSERT(vtable() == QV4::StringObject::staticVTable()); string = internalClass->engine->id_empty()->d(); *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); } -Heap::StringObject::StringObject(const QV4::String *str) +void Heap::StringObject::init(const QV4::String *str) { + Object::init(); string = str->d(); *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length()); } @@ -152,9 +154,9 @@ void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e) DEFINE_OBJECT_VTABLE(StringCtor); -Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("String")) +void Heap::StringCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("String")); } void StringCtor::construct(const Managed *m, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 54425b0909..b9f9d44fe8 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -65,8 +65,8 @@ struct StringObject : Object { LengthPropertyIndex = 0 }; - StringObject(); - StringObject(const QV4::String *string); + void init(); + void init(const QV4::String *string); String *string; Heap::String *getIndex(uint index) const; @@ -74,7 +74,7 @@ struct StringObject : Object { }; struct StringCtor : FunctionObject { - StringCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index ae5ebcad1b..009c573bf8 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -202,10 +202,10 @@ const TypedArrayOperations operations[Heap::TypedArray::NTypes] = { }; -Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t) - : Heap::FunctionObject(scope, QLatin1String(operations[t].name)) - , type(t) +void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t) { + Heap::FunctionObject::init(scope, QLatin1String(operations[t].name)); + type = t; } void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callData) @@ -363,10 +363,11 @@ void TypedArrayCtor::call(const Managed *that, Scope &scope, CallData *callData) construct(that, scope, callData); } -Heap::TypedArray::TypedArray(Type t) - : type(operations + t), - arrayType(t) +void Heap::TypedArray::init(Type t) { + Object::init(); + type = operations + t; + arrayType = t; } Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t) diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index d96027b96a..0112d2e4a1 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -86,7 +86,7 @@ struct TypedArray : Object { NTypes }; - TypedArray(Type t); + void init(Type t); const TypedArrayOperations *type; Pointer buffer; @@ -96,13 +96,13 @@ struct TypedArray : Object { }; struct TypedArrayCtor : FunctionObject { - TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t); + void init(QV4::ExecutionContext *scope, TypedArray::Type t); TypedArray::Type type; }; struct TypedArrayPrototype : Object { - inline TypedArrayPrototype(TypedArray::Type t); + inline void init(TypedArray::Type t); TypedArray::Type type; }; @@ -160,10 +160,11 @@ struct TypedArrayPrototype : Object static ReturnedValue method_subarray(CallContext *ctx); }; -inline -Heap::TypedArrayPrototype::TypedArrayPrototype(TypedArray::Type t) - : type(t) +inline void +Heap::TypedArrayPrototype::init(TypedArray::Type t) { + Object::init(); + type = t; } } // namespace QV4 diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 78cd4de9fb..6e28e21887 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -428,7 +428,7 @@ public: template Value &operator=(const Scoped &t); }; -Q_STATIC_ASSERT(std::is_trivial::value); +V4_ASSERT_IS_TRIVIAL(Value) inline bool Value::isString() const { diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index eff4db268c..b26dd27913 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -50,13 +50,15 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(VariantObject); -Heap::VariantObject::VariantObject() +void Heap::VariantObject::init() { + Object::init(); scarceData = new ExecutionEngine::ScarceResourceData; } -Heap::VariantObject::VariantObject(const QVariant &value) +void Heap::VariantObject::init(const QVariant &value) { + Object::init(); scarceData = new ExecutionEngine::ScarceResourceData(value); if (isScarce()) removeVmePropertyReference(); diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 5a6644bdcf..efaf5e1e65 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -66,8 +66,8 @@ namespace Heap { struct VariantObject : Object { - VariantObject(); - VariantObject(const QVariant &value); + void init(); + void init(const QVariant &value); void destroy() { Q_ASSERT(scarceData); if (isScarce()) diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index d15d14e463..abbe85c04e 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -58,6 +58,12 @@ // parent's init all up the inheritance chain), define QML_CHECK_INIT_DESTROY_CALLS below. #undef QML_CHECK_INIT_DESTROY_CALLS +#if defined(_MSC_VER) && (_MSC_VER < 1900) // broken compilers: +# define V4_ASSERT_IS_TRIVIAL(x) +#else // working compilers: +# define V4_ASSERT_IS_TRIVIAL(x) Q_STATIC_ASSERT(std::is_trivial< x >::value); +#endif + QT_BEGIN_NAMESPACE namespace QV4 { @@ -82,6 +88,8 @@ struct VTable namespace Heap { struct Q_QML_EXPORT Base { + void *operator new(size_t) = delete; + quintptr mm_data; // vtable and markbit inline ReturnedValue asReturnedValue() const; @@ -128,13 +136,19 @@ struct Q_QML_EXPORT Base { void init() { setInitialized(); } #ifdef QML_CHECK_INIT_DESTROY_CALLS bool _isInitialized; - void _checkIsInitialized() { Q_ASSERT(_isInitialized); } + void _checkIsInitialized() { + if (!_isInitialized) + fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n", + vtable()->className); + Q_ASSERT(_isInitialized); + } void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; } #else Q_ALWAYS_INLINE void _checkIsInitialized() {} Q_ALWAYS_INLINE void setInitialized() {} #endif }; +V4_ASSERT_IS_TRIVIAL(Base) template struct Pointer { @@ -148,7 +162,7 @@ struct Pointer { T *ptr; }; -Q_STATIC_ASSERT(std::is_trivial>::value); +V4_ASSERT_IS_TRIVIAL(Pointer) } @@ -204,7 +218,7 @@ private: QtSharedPointer::ExternalRefCountData *d; QObject *qObject; }; -Q_STATIC_ASSERT(std::is_trivial>::value); +V4_ASSERT_IS_TRIVIAL(QQmlQPointer) #endif } diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index cfd348e14a..e68fc07a46 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -108,6 +108,7 @@ public: template inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) { + V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data) size = align(size); Heap::Base *o = allocData(size, unmanagedSize); o->setVtable(ManagedType::staticVTable()); @@ -142,7 +143,6 @@ public: template typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data), unmanagedSize)); t->d_unchecked()->init(this, arg1); @@ -154,7 +154,7 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject(ic)); - (void)new (t->d()) typename ObjectType::Data(); + t->d_unchecked()->init(); return t->d(); } @@ -163,8 +163,8 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(); return t->d(); } @@ -173,8 +173,8 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1); return t->d(); } @@ -183,8 +183,8 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1, arg2); return t->d(); } @@ -193,8 +193,8 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1, arg2, arg3); return t->d(); } @@ -203,8 +203,8 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1, arg2, arg3, arg4); return t->d(); } @@ -213,7 +213,7 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject()); - (void)new (t->d()) typename ObjectType::Data(); + t->d_unchecked()->init(); return t->d(); } @@ -222,7 +222,7 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject()); - (void)new (t->d()) typename ObjectType::Data(arg1); + t->d_unchecked()->init(arg1); return t->d(); } @@ -231,7 +231,7 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject()); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2); + t->d_unchecked()->init(arg1, arg2); return t->d(); } @@ -240,7 +240,7 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject()); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3); + t->d_unchecked()->init(arg1, arg2, arg3); return t->d(); } @@ -249,7 +249,7 @@ public: { Scope scope(engine); Scoped t(scope, allocateObject()); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4); + t->d_unchecked()->init(arg1, arg2, arg3, arg4); return t->d(); } @@ -257,7 +257,6 @@ public: template typename ManagedType::Data *alloc() { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(); @@ -267,7 +266,6 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1) { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1); @@ -277,7 +275,6 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2) { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2); @@ -287,7 +284,6 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3); @@ -297,7 +293,6 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3, arg4); @@ -307,7 +302,6 @@ public: template typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { - Q_STATIC_ASSERT(std::is_trivial::value); // TODO: move down to allocManaged Scope scope(engine); Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5); diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 9a993d4ec3..23b8e5a712 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1058,7 +1058,7 @@ namespace QV4 { namespace Heap { struct QmlIncubatorObject : Object { - QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); + void init(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); inline void destroy(); QQmlComponentIncubator *incubator; QQmlQPointer parent; @@ -1484,10 +1484,11 @@ QQmlComponentExtension::~QQmlComponentExtension() { } -QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m) - : valuemap(QV4::Primitive::undefinedValue()) - , statusChanged(QV4::Primitive::undefinedValue()) +void QV4::Heap::QmlIncubatorObject::init(QQmlIncubator::IncubationMode m) { + Object::init(); + valuemap = QV4::Primitive::undefinedValue(); + statusChanged = QV4::Primitive::undefinedValue(); parent.init(); qmlContext = nullptr; incubator = new QQmlComponentIncubator(this, m); diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 95ff7b866f..8827216136 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -61,11 +61,12 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlContextWrapper); -Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext) - : readOnly(true) - , ownsContext(ownsContext) - , isNullWrapper(false) +void Heap::QmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject, bool ownsContext) { + Object::init(); + readOnly = true; + this->ownsContext = ownsContext; + isNullWrapper = false; this->context = new QQmlGuardedContextData(context); this->scopeObject.init(scopeObject); } diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index 9e5ba4a10c..126ffecf0d 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -64,7 +64,7 @@ namespace QV4 { namespace Heap { struct QmlContextWrapper : Object { - QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); + void init(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); void destroy(); bool readOnly; bool ownsContext; diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 4bc0e11340..91225a1fea 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -52,8 +52,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlListWrapper); -Heap::QmlListWrapper::QmlListWrapper() +void Heap::QmlListWrapper::init() { + Object::init(); object.init(); QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); @@ -75,7 +76,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i Scoped r(scope, engine->memoryManager->allocObject()); r->d()->object = object; r->d()->propertyType = propType; - void *args[] = { &r->d()->property, 0 }; + void *args[] = { &r->d()->property(), 0 }; QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args); return r.asReturnedValue(); } @@ -86,7 +87,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp Scoped r(scope, engine->memoryManager->allocObject()); r->d()->object = prop.object; - r->d()->property = prop; + r->d()->property() = prop; r->d()->propertyType = propType; return r.asReturnedValue(); } @@ -96,7 +97,7 @@ QVariant QmlListWrapper::toVariant() const if (!d()->object) return QVariant(); - return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property, d()->propertyType, engine()->qmlEngine())); + return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property(), d()->propertyType, engine()->qmlEngine())); } @@ -107,7 +108,7 @@ ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasPrope QV4::ExecutionEngine *v4 = w->engine(); if (name->equals(v4->id_length()) && !w->d()->object.isNull()) { - quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0; + quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0; return Primitive::fromUInt32(count).asReturnedValue(); } @@ -126,11 +127,11 @@ ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *has const QmlListWrapper *w = static_cast(m); QV4::ExecutionEngine *v4 = w->engine(); - quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0; - if (index < count && w->d()->property.at) { + quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0; + if (index < count && w->d()->property().at) { if (hasProperty) *hasProperty = true; - return QV4::QObjectWrapper::wrap(v4, w->d()->property.at(&w->d()->property, index)); + return QV4::QObjectWrapper::wrap(v4, w->d()->property().at(&w->d()->property(), index)); } if (hasProperty) @@ -152,12 +153,12 @@ void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name *index = UINT_MAX; Q_ASSERT(m->as()); QmlListWrapper *w = static_cast(m); - quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0; + quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0; if (it->arrayIndex < count) { *index = it->arrayIndex; ++it->arrayIndex; *attrs = QV4::Attr_Data; - p->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property.at(&w->d()->property, *index)); + p->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property().at(&w->d()->property(), *index)); return; } return QV4::Object::advanceIterator(m, it, name, index, p, attrs); diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index 18038d2a80..d01b332159 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -66,11 +66,18 @@ namespace QV4 { namespace Heap { struct QmlListWrapper : Object { - QmlListWrapper(); + void init(); void destroy(); QQmlQPointer object; - QQmlListProperty property; + + QQmlListProperty &property() { + return *reinterpret_cast*>(propertyData); + } + int propertyType; + +private: + void *propertyData[sizeof(QQmlListProperty)/sizeof(void*)]; }; } diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 4494fa9b53..ea1b7bf369 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -143,7 +143,7 @@ namespace QV4 { namespace Heap { struct QQmlLocaleData : Object { - inline QQmlLocaleData() { locale = new QLocale; } + inline void init() { locale = new QLocale; } void destroy() { delete locale; } QLocale *locale; }; diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index c8e2e5387c..a3ac207fc3 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -55,9 +55,10 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlTypeWrapper); -Heap::QmlTypeWrapper::QmlTypeWrapper() - : mode(IncludeEnums) +void Heap::QmlTypeWrapper::init() { + Object::init(); + mode = IncludeEnums; object.init(); } diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index fe75aefca9..3b0ae04cc1 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -71,7 +71,7 @@ struct QmlTypeWrapper : Object { ExcludeEnums }; - QmlTypeWrapper(); + void init(); void destroy(); TypeNameMode mode; QQmlQPointer object; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 2279b72cbe..11849d2c63 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -63,8 +63,11 @@ namespace Heap { struct QQmlValueTypeReference : QQmlValueTypeWrapper { - QQmlValueTypeReference() { object.init(); } - ~QQmlValueTypeReference() { object.destroy(); } + void init() { + QQmlValueTypeWrapper::init(); + object.init(); + } + void destroy() { object.destroy(); } QQmlQPointer object; int property; }; @@ -86,7 +89,7 @@ DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeReference); using namespace QV4; -Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper() +void Heap::QQmlValueTypeWrapper::destroy() { if (gadgetPtr) { valueType->metaType.destruct(gadgetPtr); @@ -140,7 +143,7 @@ bool QQmlValueTypeReference::readReferenceValue() const ::operator delete(d()->gadgetPtr); } d()->gadgetPtr =0; - d()->propertyCache = cache; + d()->setPropertyCache(cache); d()->valueType = QQmlValueTypeFactory::valueType(variantReferenceType); if (!cache) return false; @@ -163,7 +166,7 @@ bool QQmlValueTypeReference::readReferenceValue() const void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4) { - if (v4->valueTypeWrapperPrototype()->d()) + if (v4->valueTypeWrapperPrototype()->d_unchecked()) return; Scope scope(v4); @@ -180,7 +183,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj Scoped r(scope, engine->memoryManager->allocObject()); r->d()->object = object; r->d()->property = property; - r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); + r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject)); r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); r->d()->gadgetPtr = 0; return r->asReturnedValue(); @@ -192,7 +195,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria initProto(engine); Scoped r(scope, engine->memoryManager->allocObject()); - r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); + r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject)); r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); r->d()->gadgetPtr = 0; r->d()->setValue(value); @@ -218,12 +221,6 @@ bool QQmlValueTypeWrapper::toGadget(void *data) const return true; } -void QQmlValueTypeWrapper::destroy(Heap::Base *that) -{ - Heap::QQmlValueTypeWrapper *w = static_cast(that); - w->Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper(); -} - bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other) { Q_ASSERT(m && m->as() && other); @@ -243,7 +240,7 @@ PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name) Q_ASSERT(m->as()); const QQmlValueTypeWrapper *r = static_cast(m); - QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0); + QQmlPropertyData *result = r->d()->propertyCache()->property(name, 0, 0); return result ? Attr_Data : Attr_Invalid; } @@ -259,8 +256,8 @@ void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value return; } - if (that->d()->propertyCache) { - const QMetaObject *mo = that->d()->propertyCache->createMetaObject(); + if (that->d()->propertyCache()) { + const QMetaObject *mo = that->d()->propertyCache()->createMetaObject(); const int propertyCount = mo->propertyCount(); if (it->arrayIndex < static_cast(propertyCount)) { Scope scope(that->engine()); @@ -335,7 +332,7 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) } else { result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId)) + QLatin1Char('('); - const QMetaObject *mo = w->d()->propertyCache->metaObject(); + const QMetaObject *mo = w->d()->propertyCache()->metaObject(); const int propCount = mo->propertyCount(); for (int i = 0; i < propCount; ++i) { if (mo->property(i).isDesignable()) { @@ -362,7 +359,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha return Primitive::undefinedValue().asReturnedValue(); } - QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0); + QQmlPropertyData *result = r->d()->propertyCache()->property(name, 0, 0); if (!result) return Object::get(m, name, hasProperty); @@ -381,7 +378,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha return QV4::Encode(constructor(v)); \ } - const QMetaObject *metaObject = r->d()->propertyCache->metaObject(); + const QMetaObject *metaObject = r->d()->propertyCache()->metaObject(); int index = result->coreIndex(); QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index); @@ -429,8 +426,8 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) writeBackPropertyType = writebackProperty.userType(); } - const QMetaObject *metaObject = r->d()->propertyCache->metaObject(); - const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0); + const QMetaObject *metaObject = r->d()->propertyCache()->metaObject(); + const QQmlPropertyData *pd = r->d()->propertyCache()->property(name, 0, 0); if (!pd) return; diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index 94eeba366a..b8ca5a16f4 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -66,14 +66,24 @@ namespace QV4 { namespace Heap { struct QQmlValueTypeWrapper : Object { - QQmlValueTypeWrapper() {} - ~QQmlValueTypeWrapper(); - QQmlRefPointer propertyCache; + void init() { Object::init(); } + void destroy(); + QQmlPropertyCache *propertyCache() const { return _propertyCache; } + void setPropertyCache(QQmlPropertyCache *c) { + if (c) + c->addref(); + if (_propertyCache) + _propertyCache->release(); + _propertyCache = c; + } mutable void *gadgetPtr; QQmlValueType *valueType; void setValue(const QVariant &value) const; QVariant toVariant() const; + +private: + QQmlPropertyCache *_propertyCache; }; } @@ -82,7 +92,7 @@ struct Q_QML_EXPORT QQmlValueTypeWrapper : Object { V4_OBJECT2(QQmlValueTypeWrapper, Object) V4_PROTOTYPE(valueTypeWrapperPrototype) - static void destroy(Heap::Base *b); + V4_NEEDS_DESTROY public: diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 5128fc0f08..fe2d7da694 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -174,7 +174,7 @@ public: namespace Heap { struct NamedNodeMap : Object { - NamedNodeMap(NodeImpl *data, const QList &list); + void init(NodeImpl *data, const QList &list); void destroy() { delete listPtr; if (d) @@ -191,7 +191,7 @@ struct NamedNodeMap : Object { }; struct NodeList : Object { - NodeList(NodeImpl *data); + void init(NodeImpl *data); void destroy() { if (d) d->release(); @@ -200,11 +200,11 @@ struct NodeList : Object { }; struct NodePrototype : Object { - NodePrototype(); + void init(); }; struct Node : Object { - Node(NodeImpl *data); + void init(NodeImpl *data); void destroy() { if (d) d->release(); @@ -228,9 +228,10 @@ public: static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); }; -Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList &list) - : d(data) +void Heap::NamedNodeMap::init(NodeImpl *data, const QList &list) { + Object::init(); + d = data; this->list() = list; if (d) d->addref(); @@ -253,9 +254,10 @@ public: }; -Heap::NodeList::NodeList(NodeImpl *data) - : d(data) +void Heap::NodeList::init(NodeImpl *data) { + Object::init(); + d = data; if (d) d->addref(); } @@ -294,8 +296,9 @@ public: }; -Heap::NodePrototype::NodePrototype() +void Heap::NodePrototype::init() { + Object::init(); Scope scope(internalClass->engine); ScopedObject o(scope, this); @@ -327,9 +330,10 @@ struct Node : public Object bool isNull() const; }; -Heap::Node::Node(NodeImpl *data) - : d(data) +void Heap::Node::init(NodeImpl *data) { + Object::init(); + d = data; if (d) d->addref(); } @@ -1594,7 +1598,11 @@ namespace QV4 { namespace Heap { struct QQmlXMLHttpRequestWrapper : Object { - QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request); + void init(QQmlXMLHttpRequest *request) { + Object::init(); + this->request = request; + } + void destroy() { delete request; } @@ -1602,7 +1610,7 @@ struct QQmlXMLHttpRequestWrapper : Object { }; struct QQmlXMLHttpRequestCtor : FunctionObject { - QQmlXMLHttpRequestCtor(ExecutionEngine *engine); + void init(ExecutionEngine *engine); Pointer proto; }; @@ -1615,11 +1623,6 @@ struct QQmlXMLHttpRequestWrapper : public Object V4_NEEDS_DESTROY }; -Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request) - : request(request) -{ -} - struct QQmlXMLHttpRequestCtor : public FunctionObject { V4_OBJECT2(QQmlXMLHttpRequestCtor, FunctionObject) @@ -1671,9 +1674,9 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper); -Heap::QQmlXMLHttpRequestCtor::QQmlXMLHttpRequestCtor(ExecutionEngine *engine) - : Heap::FunctionObject(engine->rootContext(), QStringLiteral("XMLHttpRequest")) +void Heap::QQmlXMLHttpRequestCtor::init(ExecutionEngine *engine) { + Heap::FunctionObject::init(engine->rootContext(), QStringLiteral("XMLHttpRequest")); Scope scope(engine); Scoped ctor(scope, this); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 222b61ae49..cf0fd57773 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -91,10 +91,11 @@ struct StaticQtMetaObject : public QObject { return &staticQtMetaObject; } }; -Heap::QtObject::QtObject(QQmlEngine *qmlEngine) - : enumeratorIterator(0) - , keyIterator(0) +void Heap::QtObject::init(QQmlEngine *qmlEngine) { + Heap::Object::init(); + enumeratorIterator = 0; + keyIterator = 0; Scope scope(internalClass->engine); ScopedObject o(scope, this); @@ -1302,17 +1303,18 @@ ReturnedValue QtObject::method_locale(CallContext *ctx) return QQmlLocale::locale(ctx->engine(), code); } -Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction) - : QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name()) +void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *originalFunction) { + QV4::Heap::FunctionObject::init(originalFunction->scope(), originalFunction->name()); + bindingLocation = new QQmlSourceLocation; this->originalFunction = originalFunction->d(); } void QQmlBindingFunction::initBindingLocation() { QV4::StackFrame frame = engine()->currentStackFrame(); - d()->bindingLocation.sourceFile = frame.source; - d()->bindingLocation.line = frame.line; + d()->bindingLocation->sourceFile = frame.source; + d()->bindingLocation->line = frame.line; } void QQmlBindingFunction::call(const Managed *that, Scope &scope, CallData *callData) @@ -1436,8 +1438,9 @@ ReturnedValue QtObject::method_get_styleHints(CallContext *ctx) } -QV4::Heap::ConsoleObject::ConsoleObject() +void QV4::Heap::ConsoleObject::init() { + Object::init(); QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); @@ -1559,6 +1562,8 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c return QV4::Encode::undefined(); } +DEFINE_OBJECT_VTABLE(ConsoleObject); + QV4::ReturnedValue ConsoleObject::method_error(CallContext *ctx) { return writeToConsole(Error, ctx); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index 8c0759679a..c4bb5504a3 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -64,7 +64,7 @@ namespace QV4 { namespace Heap { struct QtObject : Object { - QtObject(QQmlEngine *qmlEngine); + void init(QQmlEngine *qmlEngine); QObject *platform; QObject *application; @@ -77,14 +77,17 @@ struct QtObject : Object { }; struct ConsoleObject : Object { - ConsoleObject(); + void init(); }; struct QQmlBindingFunction : FunctionObject { - QQmlBindingFunction(const QV4::FunctionObject *originalFunction); + void init(const QV4::FunctionObject *originalFunction); + void destroy() { + delete bindingLocation; + } Pointer originalFunction; // Set when the binding is created later - QQmlSourceLocation bindingLocation; + QQmlSourceLocation *bindingLocation; }; } @@ -145,9 +148,7 @@ private: struct ConsoleObject : Object { - typedef Heap::ConsoleObject Data; - const Data *d() const { return static_cast(Object::d()); } - Data *d() { return static_cast(Object::d()); } + V4_OBJECT2(ConsoleObject, Object) static ReturnedValue method_error(CallContext *ctx); static ReturnedValue method_log(CallContext *ctx); diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 02a5514275..395a3e5641 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -62,21 +62,24 @@ namespace QV4 { namespace Heap { struct DelegateModelGroupFunction : FunctionObject { - DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)); + void init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)); - uint flag; QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg); + uint flag; }; struct QQmlDelegateModelGroupChange : Object { - QQmlDelegateModelGroupChange() {} + void init() { Object::init(); } - QQmlChangeSet::Change change; + QQmlChangeSet::ChangeData change; }; struct QQmlDelegateModelGroupChangeArray : Object { - QQmlDelegateModelGroupChangeArray(const QVector &changes); - void destroy() { delete changes; } + void init(const QVector &changes); + void destroy() { + delete changes; + } + QVector *changes; }; @@ -106,11 +109,11 @@ struct DelegateModelGroupFunction : QV4::FunctionObject } }; -Heap::DelegateModelGroupFunction::DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)) - : QV4::Heap::FunctionObject(scope, QStringLiteral("DelegateModelGroupFunction")) - , flag(flag) - , code(code) +void Heap::DelegateModelGroupFunction::init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)) { + QV4::Heap::FunctionObject::init(scope, QStringLiteral("DelegateModelGroupFunction")); + this->flag = flag; + this->code = code; } } @@ -3300,9 +3303,10 @@ public: } }; -QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector &changes) - : changes(new QVector(changes)) +void QV4::Heap::QQmlDelegateModelGroupChangeArray::init(const QVector &changes) { + Object::init(); + this->changes = new QVector(changes); QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->setArrayType(QV4::Heap::ArrayData::Custom); diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index a34450ebd6..6cb82fddfc 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -160,7 +160,7 @@ protected: namespace QV4 { namespace Heap { struct QQmlDelegateModelItemObject : Object { - inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item); + inline void init(QQmlDelegateModelItem *item); void destroy(); QQmlDelegateModelItem *item; }; @@ -174,9 +174,10 @@ struct QQmlDelegateModelItemObject : QV4::Object V4_NEEDS_DESTROY }; -QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QQmlDelegateModelItem *item) - : item(item) +void QV4::Heap::QQmlDelegateModelItemObject::init(QQmlDelegateModelItem *item) { + Object::init(); + this->item = item; } diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index d3ff032ae9..bd2102679b 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -162,11 +162,12 @@ namespace QV4 { namespace Heap { struct ModelObject : public QObjectWrapper { - ModelObject(QObject *object, QQmlListModel *model, int elementIndex) - : QObjectWrapper(object) - , m_model(model) - , m_elementIndex(elementIndex) - {} + void init(QObject *object, QQmlListModel *model, int elementIndex) + { + QObjectWrapper::init(object); + m_model = model; + m_elementIndex = elementIndex; + } QQmlListModel *m_model; int m_elementIndex; }; @@ -180,6 +181,7 @@ struct ModelObject : public QObjectWrapper static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); V4_OBJECT2(ModelObject, QObjectWrapper) + V4_NEEDS_DESTROY }; } // namespace QV4 diff --git a/src/qml/util/qqmlchangeset_p.h b/src/qml/util/qqmlchangeset_p.h index b7a637fb2e..8e1fa3f9f2 100644 --- a/src/qml/util/qqmlchangeset_p.h +++ b/src/qml/util/qqmlchangeset_p.h @@ -68,16 +68,31 @@ public: int offset; }; - struct Change + // The storrage for Change (below). This struct is trivial, which it has to be in order to store + // it in a QV4::Heap::Base object. The Change struct doesn't add any storage fields, so it is + // safe to cast ChangeData to/from Change. + struct ChangeData { - Change() : index(0), count(0), moveId(-1) {} - Change(int index, int count, int moveId = -1, int offset = 0) - : index(index), count(count), moveId(moveId), offset(offset) {} - int index; int count; int moveId; int offset; + }; + + struct Change: ChangeData + { + Change() { + index = 0; + count = 0; + moveId = -1; + offset = 0; + } + Change(int index, int count, int moveId = -1, int offset = 0) { + this->index = index; + this->count = count; + this->moveId = moveId; + this->offset = offset; + } bool isMove() const { return moveId >= 0; } -- cgit v1.2.3 From 6c05fe9cb760a9a26d7a1a8037aa62966a3bd344 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 21 Sep 2016 11:23:02 +0200 Subject: QQmlTypeLoader: Clean up trimCache() Any type that: a, has exactly one reference (from the type cache) b, has finished loading, and is thus either in Error or Complete state c, either has no compiled data or again exactly one reference on the compiled data (from the type) is not needed anymore and can be trimmed. The previous logic would not trim types with errors that have received compiled data by loading from a file and it was generally harder to understand. Change-Id: Ieb9ce29599411ea5516742b874cbcf3dcab03bde Reviewed-by: Michael Brasser Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypeloader.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 20bd5d2620..87100d785e 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1966,12 +1966,11 @@ void QQmlTypeLoader::trimCache() for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end; ++iter) { QQmlTypeData *typeData = iter.value(); - const bool hasError = !typeData->m_compiledData && !typeData->m_errors.isEmpty(); - const bool isNotReferenced = typeData->isComplete() && typeData->m_compiledData - && typeData->m_compiledData->count() == 1; - // typeData->m_compiledData may be set early on in the proccess of loading a file, so it's important - // to check the general loading status of the typeData before making any other decisions. - if (typeData->count() == 1 && (hasError || isNotReferenced)) { + // typeData->m_compiledData may be set early on in the proccess of loading a file, so + // it's important to check the general loading status of the typeData before making any + // other decisions. + if (typeData->count() == 1 && (typeData->isError() || typeData->isComplete()) + && (!typeData->m_compiledData || typeData->m_compiledData->count() == 1)) { // There are no live objects of this type unneededTypes.append(iter); } -- cgit v1.2.3 From 57c9d6969ac474177c77d5ea59768b39620a3b2f Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 9 Sep 2016 16:20:57 +0200 Subject: QML: Also check for correct destroy() chaining Check that the destroy() method of Heap::Base was called when a Managed object needs destruction. This checks if a call to the parent's destroy() method was accidentally omitted. Change-Id: Id025ecd6d4744bf3eab23503fbe317ed2a461138 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arraybuffer.cpp | 1 + src/qml/jsruntime/qv4arraydata_p.h | 5 ++++- src/qml/jsruntime/qv4errorobject_p.h | 5 ++++- src/qml/jsruntime/qv4functionobject.cpp | 1 + src/qml/jsruntime/qv4object_p.h | 1 + src/qml/jsruntime/qv4qobjectwrapper_p.h | 10 ++++++++-- src/qml/jsruntime/qv4regexp.cpp | 1 + src/qml/jsruntime/qv4sequenceobject.cpp | 1 + src/qml/jsruntime/qv4string_p.h | 1 + src/qml/jsruntime/qv4variantobject_p.h | 1 + src/qml/memory/qv4heap_p.h | 34 +++++++++++++++++++++++++++------ src/qml/memory/qv4mm.cpp | 4 +++- src/qml/qml/qqmlcomponent.cpp | 1 + src/qml/qml/qqmlcontextwrapper.cpp | 1 + src/qml/qml/qqmllistwrapper.cpp | 1 + src/qml/qml/qqmllocale_p.h | 5 ++++- src/qml/qml/qqmltypewrapper.cpp | 1 + src/qml/qml/qqmlvaluetypewrapper.cpp | 14 ++++++-------- src/qml/qml/qqmlxmlhttprequest.cpp | 4 ++++ src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 1 + src/qml/types/qqmldelegatemodel.cpp | 2 ++ src/qml/types/qqmllistmodel_p_p.h | 1 + 22 files changed, 76 insertions(+), 20 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 908fa52680..23075aa78c 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -118,6 +118,7 @@ void Heap::ArrayBuffer::destroy() { if (!data->ref.deref()) QTypedArrayData::deallocate(data); + Object::destroy(); } QByteArray ArrayBuffer::asByteArray() const diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 9f810a32d5..24b948f01e 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -156,7 +156,10 @@ struct SimpleArrayData : public ArrayData { V4_ASSERT_IS_TRIVIAL(SimpleArrayData) struct SparseArrayData : public ArrayData { - void destroy() { delete sparse; } + void destroy() { + delete sparse; + ArrayData::destroy(); + } uint mappedIndex(uint index) const { SparseArrayNode *n = sparse->findNode(index); diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index b7a0889e08..42a6e0b4b1 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -76,7 +76,10 @@ struct ErrorObject : Object { void init(); void init(const Value &message, ErrorType t = Error); void init(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); - void destroy() { delete stackTrace; } + void destroy() { + delete stackTrace; + Object::destroy(); + } ErrorType errorType; StackTrace *stackTrace; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 118ed89c43..2cc58b74a6 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -147,6 +147,7 @@ void Heap::FunctionObject::destroy() { if (function) function->compilationUnit->release(); + Object::destroy(); } void FunctionObject::init(String *n, bool createProto) diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 6ddeb84d3c..e13a701b0f 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -69,6 +69,7 @@ namespace Heap { struct Object : Base { void init() { Base::init(); } + void destroy() { Base::destroy(); } const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 727af6c9c6..a32244c8de 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -79,7 +79,10 @@ struct QQmlValueTypeWrapper; struct QObjectWrapper : Object { void init(QObject *object); - void destroy() { qObj.destroy(); } + void destroy() { + qObj.destroy(); + Object::destroy(); + } QObject *object() const { return qObj.data(); } @@ -131,7 +134,10 @@ struct QMetaObjectWrapper : FunctionObject { struct QmlSignalHandler : Object { void init(QObject *object, int signalIndex); - void destroy() { qObj.destroy(); } + void destroy() { + qObj.destroy(); + Object::destroy(); + } int signalIndex; QObject *object() const { return qObj.data(); } diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index c2bc905ef5..9e94c58432 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -124,6 +124,7 @@ void Heap::RegExp::destroy() #endif delete byteCode; delete pattern; + Base::destroy(); } void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 4b82a7d83f..24890fdb18 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -221,6 +221,7 @@ struct QQmlSequence : Object { void destroy() { delete container; object.destroy(); + Object::destroy(); } mutable Container *container; diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index df34ec0151..23ec3349b9 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -76,6 +76,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base { void destroy() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); + Base::destroy(); } void simplifyString() const; int length() const { diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index efaf5e1e65..9a04069c12 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -73,6 +73,7 @@ struct VariantObject : Object if (isScarce()) addVmePropertyReference(); delete scarceData; + Object::destroy(); } bool isScarce() const; int vmePropertyReferenceCount; diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index abbe85c04e..5a3797f397 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -133,19 +133,41 @@ struct Q_QML_EXPORT Base { void *operator new(size_t, Heap::Base *m) { return m; } void operator delete(void *, Heap::Base *) {} - void init() { setInitialized(); } + void init() { _setInitialized(); } + void destroy() { _setDestroyed(); } #ifdef QML_CHECK_INIT_DESTROY_CALLS - bool _isInitialized; + enum { Uninitialized = 0, Initialized, Destroyed } _livenessStatus; void _checkIsInitialized() { - if (!_isInitialized) + if (_livenessStatus == Uninitialized) fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n", vtable()->className); - Q_ASSERT(_isInitialized); + else if (_livenessStatus == Destroyed) + fprintf(stderr, "ERROR: use of object '%s' after call to destroy() !!\n", + vtable()->className); + Q_ASSERT(_livenessStatus = Initialized); + } + void _checkIsDestroyed() { + if (_livenessStatus == Initialized) + fprintf(stderr, "ERROR: object '%s' was never destroyed completely !!\n", + vtable()->className); + Q_ASSERT(_livenessStatus == Destroyed); + } + void _setInitialized() { Q_ASSERT(_livenessStatus == Uninitialized); _livenessStatus = Initialized; } + void _setDestroyed() { + if (_livenessStatus == Uninitialized) + fprintf(stderr, "ERROR: attempting to destroy an uninitialized object '%s' !!\n", + vtable()->className); + else if (_livenessStatus == Destroyed) + fprintf(stderr, "ERROR: attempting to destroy repeatedly object '%s' !!\n", + vtable()->className); + Q_ASSERT(_livenessStatus == Initialized); + _livenessStatus = Destroyed; } - void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; } #else Q_ALWAYS_INLINE void _checkIsInitialized() {} - Q_ALWAYS_INLINE void setInitialized() {} + Q_ALWAYS_INLINE void _checkIsDestroyed() {} + Q_ALWAYS_INLINE void _setInitialized() {} + Q_ALWAYS_INLINE void _setDestroyed() {} #endif }; V4_ASSERT_IS_TRIVIAL(Base) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 3d25bd1639..ad4ecfe76d 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -229,8 +229,10 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec *unmanagedHeapSize -= heapBytes; } - if (m->vtable()->destroy) + if (m->vtable()->destroy) { m->vtable()->destroy(m); + m->_checkIsDestroyed(); + } memset(m, 0, header->itemSize); #ifdef V4_USE_VALGRIND diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 23b8e5a712..8be5172cd4 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1497,6 +1497,7 @@ void QV4::Heap::QmlIncubatorObject::init(QQmlIncubator::IncubationMode m) void QV4::Heap::QmlIncubatorObject::destroy() { delete incubator; parent.destroy(); + Object::destroy(); } void QV4::QmlIncubatorObject::setInitialState(QObject *o) diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 8827216136..2418003519 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -77,6 +77,7 @@ void Heap::QmlContextWrapper::destroy() (*context)->destroy(); delete context; scopeObject.destroy(); + Object::destroy(); } ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *ctxt, QObject *scope) diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 91225a1fea..8aa107dc17 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -64,6 +64,7 @@ void Heap::QmlListWrapper::init() void Heap::QmlListWrapper::destroy() { object.destroy(); + Object::destroy(); } ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, int propType) diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index ea1b7bf369..275f58db7d 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -144,7 +144,10 @@ namespace Heap { struct QQmlLocaleData : Object { inline void init() { locale = new QLocale; } - void destroy() { delete locale; } + void destroy() { + delete locale; + Object::destroy(); + } QLocale *locale; }; diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index a3ac207fc3..5c3ad6b2a6 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -67,6 +67,7 @@ void Heap::QmlTypeWrapper::destroy() if (typeNamespace) typeNamespace->release(); object.destroy(); + Object::destroy(); } bool QmlTypeWrapper::isSingleton() const diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 11849d2c63..b23bc033d1 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -67,7 +67,10 @@ struct QQmlValueTypeReference : QQmlValueTypeWrapper QQmlValueTypeWrapper::init(); object.init(); } - void destroy() { object.destroy(); } + void destroy() { + object.destroy(); + QQmlValueTypeWrapper::destroy(); + } QQmlQPointer object; int property; }; @@ -77,8 +80,7 @@ struct QQmlValueTypeReference : QQmlValueTypeWrapper struct QQmlValueTypeReference : public QQmlValueTypeWrapper { V4_OBJECT2(QQmlValueTypeReference, QQmlValueTypeWrapper) - - static void destroy(Heap::Base *that); + V4_NEEDS_DESTROY bool readReferenceValue() const; }; @@ -95,6 +97,7 @@ void Heap::QQmlValueTypeWrapper::destroy() valueType->metaType.destruct(gadgetPtr); ::operator delete(gadgetPtr); } + Object::destroy(); } void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const @@ -491,9 +494,4 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) } } -void QQmlValueTypeReference::destroy(Heap::Base *that) -{ - static_cast(that)->Heap::QQmlValueTypeReference::~QQmlValueTypeReference(); -} - QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index fe2d7da694..f94946820f 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -179,6 +179,7 @@ struct NamedNodeMap : Object { delete listPtr; if (d) d->release(); + Object::destroy(); } QList &list() { if (listPtr == nullptr) @@ -195,6 +196,7 @@ struct NodeList : Object { void destroy() { if (d) d->release(); + Object::destroy(); } NodeImpl *d; }; @@ -208,6 +210,7 @@ struct Node : Object { void destroy() { if (d) d->release(); + Object::destroy(); } NodeImpl *d; }; @@ -1605,6 +1608,7 @@ struct QQmlXMLHttpRequestWrapper : Object { void destroy() { delete request; + Object::destroy(); } QQmlXMLHttpRequest *request; }; diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index c4bb5504a3..7602a92582 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -84,6 +84,7 @@ struct QQmlBindingFunction : FunctionObject { void init(const QV4::FunctionObject *originalFunction); void destroy() { delete bindingLocation; + Object::destroy(); } Pointer originalFunction; // Set when the binding is created later diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 395a3e5641..9b58ec35f8 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -78,6 +78,7 @@ struct QQmlDelegateModelGroupChangeArray : Object { void init(const QVector &changes); void destroy() { delete changes; + Object::destroy(); } QVector *changes; @@ -1872,6 +1873,7 @@ DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject); void QV4::Heap::QQmlDelegateModelItemObject::destroy() { item->Dispose(); + Object::destroy(); } diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index bd2102679b..6e17b55e79 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -168,6 +168,7 @@ struct ModelObject : public QObjectWrapper { m_model = model; m_elementIndex = elementIndex; } + void destroy() { QObjectWrapper::destroy(); } QQmlListModel *m_model; int m_elementIndex; }; -- cgit v1.2.3 From a6be2d77aa6dc9f834b971eaff749a02cf982525 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 7 Oct 2016 13:47:52 +0200 Subject: V4: Move zero-initialization of heap items into the header file This allows for a compiler to do dead-store elimination for zero- initialized memory that gets overwritten directly after the allocated chunk is returned. Change-Id: I6493aae8fdabc2306e7cfa1233f917b1775c4451 Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 2 +- src/qml/memory/qv4mm_p.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index ad4ecfe76d..5aaf710ee8 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -234,7 +234,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec m->_checkIsDestroyed(); } - memset(m, 0, header->itemSize); + memset(m, 0, sizeof(Heap::Base)); #ifdef V4_USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; VALGRIND_MEMPOOL_FREE(engine->memoryManager, m); diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index e68fc07a46..dfa0d85dff 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -111,6 +111,7 @@ public: V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data) size = align(size); Heap::Base *o = allocData(size, unmanagedSize); + memset(o, 0, size); o->setVtable(ManagedType::staticVTable()); return static_cast(o); } -- cgit v1.2.3 From 376077a8e73100ccada6f2bb81c6664817bb44ba Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Sat, 8 Oct 2016 13:03:35 +0200 Subject: Fix developer-build with gcc 6 Locally suppress bogus tautological compare warnings. Task-number: QTBUG-56266 Change-Id: Ic1b554982a778cdd89c8047483523c44d53bbadd Reviewed-by: Thiago Macieira --- src/qml/jsruntime/qv4arraydata.cpp | 4 ++++ src/qml/jsruntime/qv4managed_p.h | 16 +++++++++++++++- src/qml/jsruntime/qv4object_p.h | 12 ++++++++++-- src/qml/jsruntime/qv4sequenceobject.cpp | 24 ++++++++---------------- 4 files changed, 37 insertions(+), 19 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index ec0e6111ab..85d8155d3c 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -40,6 +40,8 @@ using namespace QV4; +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON + const QV4::VTable QV4::ArrayData::static_vtbl = { 0, QV4::ArrayData::IsExecutionContext, @@ -88,6 +90,8 @@ const ArrayVTable SparseArrayData::static_vtbl = SparseArrayData::length }; +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF + Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData)); Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData)); diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 6a1bd7a9a4..5bda628bf1 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -94,6 +94,18 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} #define Q_VTABLE_FUNCTION(classname, func) \ (classname::func == QV4::Managed::func ? 0 : classname::func) +// Q_VTABLE_FUNCTION triggers a bogus tautological-compare warning in GCC6+ +#if defined(Q_CC_GNU) && Q_CC_GNU >= 600 +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ + QT_WARNING_PUSH; \ + QT_WARNING_DISABLE_GCC("-Wtautological-compare") + +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \ + ;QT_WARNING_POP +#else +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF +#endif #define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \ { \ @@ -113,7 +125,9 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} } #define DEFINE_MANAGED_VTABLE(classname) \ -const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ +const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF struct Q_QML_PRIVATE_EXPORT Managed : Value { diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 4e39ccaf99..7e826b4c51 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -124,7 +124,7 @@ struct ObjectVTable void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); }; -#define DEFINE_OBJECT_VTABLE(classname) \ +#define DEFINE_OBJECT_VTABLE_BASE(classname) \ const QV4::ObjectVTable classname::static_vtbl = \ { \ DEFINE_MANAGED_VTABLE_INT(classname, (QT_PREPEND_NAMESPACE(QtPrivate)::is_same::value) ? Q_NULLPTR : &classname::SuperClass::static_vtbl.vTable), \ @@ -144,7 +144,15 @@ const QV4::ObjectVTable classname::static_vtbl = \ advanceIterator \ } - +#define DEFINE_OBJECT_VTABLE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ +DEFINE_OBJECT_VTABLE_BASE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF + +#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ +template<> DEFINE_OBJECT_VTABLE_BASE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF struct Q_QML_EXPORT Object: Managed { V4_OBJECT2(Object, Object) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 36ee848d00..7fc69a4010 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -573,29 +573,21 @@ Heap::QQmlSequence::QQmlSequence(QObject *object, int propertyIndex) namespace QV4 { typedef QQmlSequence QQmlQStringList; -template<> -DEFINE_OBJECT_VTABLE(QQmlQStringList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQStringList); typedef QQmlSequence > QQmlStringList; -template<> -DEFINE_OBJECT_VTABLE(QQmlStringList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringList); typedef QQmlSequence > QQmlIntList; -template<> -DEFINE_OBJECT_VTABLE(QQmlIntList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntList); typedef QQmlSequence > QQmlUrlList; -template<> -DEFINE_OBJECT_VTABLE(QQmlUrlList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlList); typedef QQmlSequence QQmlQModelIndexList; -template<> -DEFINE_OBJECT_VTABLE(QQmlQModelIndexList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList); typedef QQmlSequence QQmlQItemSelectionRangeList; -template<> -DEFINE_OBJECT_VTABLE(QQmlQItemSelectionRangeList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQItemSelectionRangeList); typedef QQmlSequence > QQmlBoolList; -template<> -DEFINE_OBJECT_VTABLE(QQmlBoolList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolList); typedef QQmlSequence > QQmlRealList; -template<> -DEFINE_OBJECT_VTABLE(QQmlRealList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealList); } -- cgit v1.2.3 From 4b14c4b4da2294926d649ea767cc22b14bc3061e Mon Sep 17 00:00:00 2001 From: Arnaud Vrac Date: Wed, 14 Sep 2016 11:21:36 +0200 Subject: Fix corruption when adding or changing properties of JS objects Commit 833c99db20 introduced this regression by only moving part of the value data to the proper offset. Task-number: QTBUG-53261 Change-Id: I11241c57057a57794bc3ca60ee437206e524f355 Reviewed-by: Ulf Hermann Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4internalclass.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 0bc4b9a7fc..65e83d848c 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -140,16 +140,20 @@ static void insertHoleIntoPropertyData(Object *object, int idx) int icSize = object->internalClass()->size; int from = qMax(idx, inlineSize); int to = from + 1; - if (from < icSize) - memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1); + if (from < icSize) { + memmove(object->propertyData(to), object->propertyData(from), + (icSize - from - 1) * sizeof(Value)); + } if (from == idx) return; if (inlineSize < icSize) *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1); from = idx; to = from + 1; - if (from < inlineSize - 1) - memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1); + if (from < inlineSize - 1) { + memmove(object->propertyData(to), object->propertyData(from), + (inlineSize - from - 1) * sizeof(Value)); + } } static void removeFromPropertyData(Object *object, int idx, bool accessor = false) -- cgit v1.2.3 From a191de3f4dd777e8e60b4d3b5684b59d22be068d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 12 Sep 2016 13:15:20 +0200 Subject: Fix V4 on big-endian We can't both invert offset position and inter-value positions of tag and value. This patch changes 32-bit big-endian to use the same order inside the tag/value but just at different offsets. This also make it compatible with how we use it with doubles. This fixes value/tag reads on 32-bit big-endian and offsets on 64-bit. Task-number: QTBUG-56271 Change-Id: I95cf792c29ac3f42a4018ce1f115193c143a0df0 (cherry picked from commit 2a658344397729450f869138bf77e063a0a6166b) Reviewed-by: Shawn Rutledge --- src/qml/jsruntime/qv4value_p.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 02425c52a5..ebe43b505d 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -158,19 +158,16 @@ public: Q_ALWAYS_INLINE quint64 rawValue() const { return _val; } Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; } -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN || defined(QV4_USE_64_BIT_VALUE_ENCODING) +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static inline int valueOffset() { return 0; } static inline int tagOffset() { return 4; } - Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; } - Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); } - Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; } -#else // !Q_LITTLE_ENDIAN && !defined(QV4_USE_64_BIT_VALUE_ENCODING) +#else // !Q_LITTLE_ENDIAN static inline int valueOffset() { return 4; } static inline int tagOffset() { return 0; } - Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; } - Q_ALWAYS_INLINE quint32 tag() const { return _val & quint64(~quint32(0)); } - Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; } #endif + Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; } + Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); } + Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; } #if defined(V4_BOOTSTRAP) Q_ALWAYS_INLINE Heap::Base *m() const { Q_UNREACHABLE(); return Q_NULLPTR; } -- cgit v1.2.3 From e48c4134afcb8d4b33c3e965ce5d94e629982d2e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 11 Aug 2016 15:46:45 +0200 Subject: Convert qtdeclarative over to use the new configure system Change-Id: I105d46e1a4e666f11c07ad63aa24a7c388da1be6 Reviewed-by: Oswald Buddenhagen --- src/qml/configure.json | 7 +++++++ src/qml/qtqmlglobal.h | 2 ++ src/qml/qtqmlglobal_p.h | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/qml/configure.json (limited to 'src/qml') diff --git a/src/qml/configure.json b/src/qml/configure.json new file mode 100644 index 0000000000..34b83ba9ff --- /dev/null +++ b/src/qml/configure.json @@ -0,0 +1,7 @@ +{ + "module": "qml", + "depends": [ + "core-private", + "network-private" + ] +} diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h index 34191d06b2..8529e1f980 100644 --- a/src/qml/qtqmlglobal.h +++ b/src/qml/qtqmlglobal.h @@ -41,6 +41,8 @@ #define QTQMLGLOBAL_H #include +#include +#include QT_BEGIN_NAMESPACE diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h index 1b0872298d..63585fd62e 100644 --- a/src/qml/qtqmlglobal_p.h +++ b/src/qml/qtqmlglobal_p.h @@ -51,7 +51,9 @@ // We mean it. // -#include "qtqmlglobal.h" +#include +#include +#include #if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB) # define Q_QML_PRIVATE_EXPORT -- cgit v1.2.3 From 11e0e5574a529e337e43ab15fca357b109ea2834 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 5 Sep 2016 13:12:58 +0200 Subject: Make the Moth interpreter configurable Change-Id: I2b784820c4e39a7932f81bfee9ce78e01a2e96b5 Reviewed-by: Oswald Buddenhagen Reviewed-by: Simon Hausmann --- src/qml/compiler/compiler.pri | 14 ++++++++++---- src/qml/compiler/qv4instr_moth_p.h | 5 +++-- src/qml/compiler/qv4isel_moth_p.h | 2 ++ src/qml/configure.json | 23 +++++++++++++++++++++++ src/qml/jsruntime/jsruntime.pri | 9 +++++++-- src/qml/jsruntime/qv4engine.cpp | 6 ++++++ src/qml/jsruntime/qv4vme_moth_p.h | 3 +++ 7 files changed, 54 insertions(+), 8 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri index e49f5c40a5..a63de67b4c 100644 --- a/src/qml/compiler/compiler.pri +++ b/src/qml/compiler/compiler.pri @@ -25,8 +25,6 @@ SOURCES += \ HEADERS += \ $$PWD/qqmltypecompiler_p.h \ - $$PWD/qv4isel_moth_p.h \ - $$PWD/qv4instr_moth_p.h \ $$PWD/qqmlpropertycachecreator_p.h \ $$PWD/qqmlpropertyvalidator_p.h \ $$PWD/qv4compilationunitmapper_p.h @@ -34,8 +32,6 @@ HEADERS += \ SOURCES += \ $$PWD/qqmltypecompiler.cpp \ - $$PWD/qv4instr_moth.cpp \ - $$PWD/qv4isel_moth.cpp \ $$PWD/qqmlpropertycachecreator.cpp \ $$PWD/qqmlpropertyvalidator.cpp \ $$PWD/qv4compilationunitmapper.cpp @@ -43,4 +39,14 @@ SOURCES += \ unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp +qtConfig(qml-interpreter) { + HEADERS += \ + $$PWD/qv4instr_moth_p.h \ + $$PWD/qv4isel_moth_p.h + SOURCES += \ + $$PWD/qv4instr_moth.cpp \ + $$PWD/qv4isel_moth.cpp +} + + } diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index beb43376ee..b83bcdb83b 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -50,12 +50,13 @@ // // We mean it. // - -#include +#include #include #include #include +QT_REQUIRE_CONFIG(qml_interpreter); + QT_BEGIN_NAMESPACE #ifdef QT_NO_QML_DEBUGGER diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index c304284cbc..74323a2912 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -58,6 +58,8 @@ #include #include "qv4instr_moth_p.h" +QT_REQUIRE_CONFIG(qml_interpreter); + QT_BEGIN_NAMESPACE namespace QV4 { diff --git a/src/qml/configure.json b/src/qml/configure.json index 34b83ba9ff..b3a7f9d8f2 100644 --- a/src/qml/configure.json +++ b/src/qml/configure.json @@ -3,5 +3,28 @@ "depends": [ "core-private", "network-private" + ], + + "commandline": { + "options": { + "qml-interpreter": "boolean" + } + }, + + "features": { + "qml-interpreter": { + "label": "QML interpreter", + "purpose": "Support for the QML interpreter", + "output": [ "privateFeature" ] + } + }, + + "summary": [ + { + "section": "Qt QML", + "entries": [ + "qml-interpreter" + ] + } ] } diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index e72b06359e..dcc04cbd54 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -38,7 +38,6 @@ SOURCES += \ $$PWD/qv4sequenceobject.cpp \ $$PWD/qv4include.cpp \ $$PWD/qv4qobjectwrapper.cpp \ - $$PWD/qv4vme_moth.cpp \ $$PWD/qv4arraybuffer.cpp \ $$PWD/qv4typedarray.cpp \ $$PWD/qv4dataview.cpp @@ -88,12 +87,18 @@ HEADERS += \ $$PWD/qv4sequenceobject_p.h \ $$PWD/qv4include_p.h \ $$PWD/qv4qobjectwrapper_p.h \ - $$PWD/qv4vme_moth_p.h \ $$PWD/qv4profiling_p.h \ $$PWD/qv4arraybuffer_p.h \ $$PWD/qv4typedarray_p.h \ $$PWD/qv4dataview_p.h +qtConfig(qml-interpreter) { + HEADERS += \ + $$PWD/qv4vme_moth_p.h + SOURCES += \ + $$PWD/qv4vme_moth.cpp +} + } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f630dfaee0..a9284f2e69 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -86,7 +86,9 @@ #include "qv4isel_masm_p.h" #endif // V4_ENABLE_JIT +#if QT_CONFIG(qml_interpreter) #include "qv4isel_moth_p.h" +#endif #if USE(PTHREADS) # include @@ -160,6 +162,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) MemoryManager::GCBlocker gcBlocker(memoryManager); if (!factory) { +#if QT_CONFIG(qml_interpreter) bool jitDisabled = true; #ifdef V4_ENABLE_JIT @@ -180,6 +183,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) "very slow. Visit https://wiki.qt.io/V4 to learn about possible " "solutions for your platform."); } +#else + factory = new JIT::ISelFactory; +#endif } iselFactory.reset(factory); diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h index cd8d335f1c..f8893509d9 100644 --- a/src/qml/jsruntime/qv4vme_moth_p.h +++ b/src/qml/jsruntime/qv4vme_moth_p.h @@ -51,9 +51,12 @@ // We mean it. // +#include #include #include +QT_REQUIRE_CONFIG(qml_interpreter); + QT_BEGIN_NAMESPACE namespace QV4 { -- cgit v1.2.3 From 4ee2bc4e9c05d8daec8b04412a0b7c0264fbc1a4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 15 Aug 2016 10:35:53 +0200 Subject: Turn the no-network support into a configurable feature Change-Id: Ic70f60c124fe166b37fbe9b853735be3c5e0d46d Reviewed-by: Oswald Buddenhagen Reviewed-by: Simon Hausmann --- src/qml/configure.json | 11 +++++-- src/qml/jsruntime/qv4include.cpp | 14 ++++---- src/qml/jsruntime/qv4include_p.h | 4 +-- src/qml/qml.pro | 5 +-- src/qml/qml/qqmlengine.cpp | 8 ++--- src/qml/qml/qqmlengine.h | 4 +-- src/qml/qml/qqmlengine_p.h | 2 +- src/qml/qml/qqmlfile.cpp | 20 +++++------ src/qml/qml/qqmlfile.h | 2 +- src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp | 4 +-- src/qml/qml/qqmlnetworkaccessmanagerfactory.h | 4 +-- src/qml/qml/qqmltypeloader.cpp | 44 ++++++++++++------------- src/qml/qml/qqmltypeloader_p.h | 13 ++++---- src/qml/qml/qqmlxmlhttprequest.cpp | 4 +-- src/qml/qml/qqmlxmlhttprequest_p.h | 4 +-- src/qml/qml/v8/qv8engine.cpp | 6 ++-- src/qml/qml/v8/qv8engine_p.h | 2 +- src/qml/qtqmlglobal.h | 2 ++ src/qml/types/qquickworkerscript.cpp | 12 +++---- 19 files changed, 87 insertions(+), 78 deletions(-) (limited to 'src/qml') diff --git a/src/qml/configure.json b/src/qml/configure.json index b3a7f9d8f2..d22ba3b8f0 100644 --- a/src/qml/configure.json +++ b/src/qml/configure.json @@ -7,7 +7,8 @@ "commandline": { "options": { - "qml-interpreter": "boolean" + "qml-interpreter": "boolean", + "qml-network": "boolean" } }, @@ -16,6 +17,11 @@ "label": "QML interpreter", "purpose": "Support for the QML interpreter", "output": [ "privateFeature" ] + }, + "qml-network": { + "label": "QML network support", + "purpose": "Provides network transparency for QML", + "output": [ "publicFeature" ] } }, @@ -23,7 +29,8 @@ { "section": "Qt QML", "entries": [ - "qml-interpreter" + "qml-interpreter", + "qml-network" ] } ] diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index c33d2cad11..be8057e9f5 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -41,7 +41,7 @@ #include "qv4scopedvalue_p.h" #include -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) #include #include #endif @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &callback) : v4(engine), m_url(url) -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) , m_redirectCount(0), m_network(0) , m_reply(0) #endif { @@ -71,7 +71,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, m_resultObject.set(v4, resultValue(v4)); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) m_network = engine->v8Engine->networkAccessManager(); QNetworkRequest request; @@ -86,7 +86,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4Include::~QV4Include() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) delete m_reply; m_reply = 0; #endif @@ -135,7 +135,7 @@ QV4::ReturnedValue QV4Include::result() #define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15 void QV4Include::finished() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) m_redirectCount++; if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) { @@ -184,7 +184,7 @@ void QV4Include::finished() QV4::ScopedObject resultObj(scope, m_resultObject.value()); QV4::ScopedString status(scope, v4->newString(QStringLiteral("status"))); resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError))); -#endif //QT_NO_NETWORK +#endif // qml_network QV4::ScopedValue cb(scope, m_callbackFunction.value()); callback(cb, resultObj); @@ -211,7 +211,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) if (ctx->argc() >= 2 && ctx->args()[1].as()) callbackFunction = ctx->args()[1]; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow())); if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor()) url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile); diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h index 1750e6a7e1..4c601a5e7b 100644 --- a/src/qml/jsruntime/qv4include_p.h +++ b/src/qml/jsruntime/qv4include_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QQmlEngine; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) class QNetworkAccessManager; #endif class QNetworkReply; @@ -94,7 +94,7 @@ private: QV4::ExecutionEngine *v4; QUrl m_url; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) int m_redirectCount; QNetworkAccessManager *m_network; QPointer m_reply; diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 13e00d8812..84c3f04349 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -1,11 +1,8 @@ TARGET = QtQml QT = core-private -no_network { - DEFINES += QT_NO_NETWORK -} else { +qtConfig(qml-network): \ QT += network -} DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index cb51c18925..c10aa0129c 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -70,7 +70,7 @@ #include #include -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) #include "qqmlnetworkaccessmanagerfactory.h" #include #include @@ -646,7 +646,7 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e) cleanup(0), erroredBindings(0), inProgressCreations(0), workerScriptEngine(0), activeObjectCreator(0), -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) networkAccessManager(0), networkAccessManagerFactory(0), #endif urlInterceptor(0), scarceResourcesRefCount(0), importDatabase(e), typeLoader(e), @@ -1129,7 +1129,7 @@ void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) } } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) /*! Sets the \a factory to use for creating QNetworkAccessManager(s). @@ -1196,7 +1196,7 @@ QNetworkAccessManager *QQmlEngine::networkAccessManager() const Q_D(const QQmlEngine); return d->getNetworkAccessManager(); } -#endif // QT_NO_NETWORK +#endif // qml_network /*! diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index bbb9c36ce9..2c0c39d0b4 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -87,7 +87,7 @@ class QQmlExpression; class QQmlContext; class QQmlType; class QUrl; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) class QNetworkAccessManager; class QQmlNetworkAccessManagerFactory; #endif @@ -117,7 +117,7 @@ public: bool importPlugin(const QString &filePath, const QString &uri, QList *errors); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *); QQmlNetworkAccessManagerFactory *networkAccessManagerFactory() const; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 713b03dbf3..916566b6c7 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -162,7 +162,7 @@ public: void registerFinalizeCallback(QObject *obj, int index); QQmlObjectCreator *activeObjectCreator; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const; QNetworkAccessManager *getNetworkAccessManager() const; mutable QNetworkAccessManager *networkAccessManager; diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp index 4769402855..4e4db086b0 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -68,7 +68,7 @@ static char assets_string[] = "assets"; class QQmlFilePrivate; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) class QQmlFileNetworkReply : public QObject { Q_OBJECT @@ -117,12 +117,12 @@ public: Error error; QString errorString; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QQmlFileNetworkReply *reply; #endif }; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) int QQmlFileNetworkReply::finishedIndex = -1; int QQmlFileNetworkReply::downloadProgressIndex = -1; int QQmlFileNetworkReply::networkFinishedIndex = -1; @@ -205,11 +205,11 @@ void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b) { emit downloadProgress(a, b); } -#endif // QT_NO_NETWORK +#endif // qml_network QQmlFilePrivate::QQmlFilePrivate() : error(None) -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) , reply(0) #endif { @@ -233,7 +233,7 @@ QQmlFile::QQmlFile(QQmlEngine *e, const QString &url) QQmlFile::~QQmlFile() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) delete d->reply; #endif delete d; @@ -273,7 +273,7 @@ QQmlFile::Status QQmlFile::status() const { if (d->url.isEmpty() && d->urlString.isEmpty()) return Null; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) else if (d->reply) return Loading; #endif @@ -333,7 +333,7 @@ void QQmlFile::load(QQmlEngine *engine, const QUrl &url) d->error = QQmlFilePrivate::NotFound; } } else { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) d->reply = new QQmlFileNetworkReply(engine, d, url); #else d->error = QQmlFilePrivate::NotFound; @@ -364,7 +364,7 @@ void QQmlFile::load(QQmlEngine *engine, const QString &url) d->error = QQmlFilePrivate::NotFound; } } else { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QUrl qurl(url); d->url = qurl; d->urlString = QString(); @@ -388,7 +388,7 @@ void QQmlFile::clear(QObject *) clear(); } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) bool QQmlFile::connectFinished(QObject *object, const char *method) { if (!d || !d->reply) { diff --git a/src/qml/qml/qqmlfile.h b/src/qml/qml/qqmlfile.h index 3dd683a2cd..aec0981a95 100644 --- a/src/qml/qml/qqmlfile.h +++ b/src/qml/qml/qqmlfile.h @@ -80,7 +80,7 @@ public: void clear(); void clear(QObject *); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) bool connectFinished(QObject *, const char *); bool connectFinished(QObject *, int); bool connectDownloadProgress(QObject *, const char *); diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp index c94db8e168..1680253d73 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp @@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) /*! \class QQmlNetworkAccessManagerFactory @@ -103,6 +103,6 @@ QQmlNetworkAccessManagerFactory::~QQmlNetworkAccessManagerFactory() implementation of this method is reentrant. */ -#endif //QT_NO_NETWORK +#endif // qml_network QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h index ba3561b9f4..57dec1da29 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) class QNetworkAccessManager; class Q_QML_EXPORT QQmlNetworkAccessManagerFactory @@ -56,7 +56,7 @@ public: }; -#endif //QT_NO_NETWORK +#endif // qml_network QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 87100d785e..1f1c9d7150 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -123,7 +123,7 @@ namespace { }; } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) // This is a lame object that we need to ensure that slots connected to // QNetworkReply get called in the correct thread (the loader thread). // As QQmlTypeLoader lives in the main thread, and we can't use @@ -143,7 +143,7 @@ public slots: private: QQmlTypeLoader *l; }; -#endif // QT_NO_NETWORK +#endif // qml_network class QQmlTypeLoaderThread : public QQmlThread { @@ -151,10 +151,10 @@ class QQmlTypeLoaderThread : public QQmlThread public: QQmlTypeLoaderThread(QQmlTypeLoader *loader); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkAccessManager *networkAccessManager() const; QQmlTypeLoaderNetworkReplyProxy *networkReplyProxy() const; -#endif // QT_NO_NETWORK +#endif // qml_network void load(QQmlDataBlob *b); void loadAsync(QQmlDataBlob *b); void loadWithStaticData(QQmlDataBlob *b, const QByteArray &); @@ -177,13 +177,13 @@ private: void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri); QQmlTypeLoader *m_loader; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) mutable QNetworkAccessManager *m_networkAccessManager; mutable QQmlTypeLoaderNetworkReplyProxy *m_networkReplyProxy; -#endif // QT_NO_NETWORK +#endif // qml_network }; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QQmlTypeLoaderNetworkReplyProxy::QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l) : l(l) { @@ -212,7 +212,7 @@ void QQmlTypeLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply) l->networkReplyProgress(reply, replySize, replySize); l->networkReplyFinished(reply); } -#endif // QT_NO_NETWORK +#endif // qml_network /*! \class QQmlDataBlob @@ -529,7 +529,7 @@ void QQmlDataBlob::done() { } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) /*! Invoked if there is a network error while fetching this blob. @@ -582,7 +582,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError) setError(error); } -#endif // QT_NO_NETWORK +#endif // qml_network /*! Called if \a blob, which was previously waited for, has an error. @@ -782,15 +782,15 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v) QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader) : m_loader(loader) -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) , m_networkAccessManager(0), m_networkReplyProxy(0) -#endif // QT_NO_NETWORK +#endif // qml_network { // Do that after initializing all the members. startup(); } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const { Q_ASSERT(isThisThread()); @@ -808,7 +808,7 @@ QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first return m_networkReplyProxy; } -#endif // QT_NO_NETWORK +#endif // qml_network void QQmlTypeLoaderThread::load(QQmlDataBlob *b) { @@ -866,12 +866,12 @@ void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface, void QQmlTypeLoaderThread::shutdownThread() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) delete m_networkAccessManager; m_networkAccessManager = 0; delete m_networkReplyProxy; m_networkReplyProxy = 0; -#endif // QT_NO_NETWORK +#endif // qml_network } void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b) @@ -957,14 +957,14 @@ void QQmlTypeLoader::invalidate() m_thread = 0; } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) // Need to delete the network replies after // the loader thread is shutdown as it could be // getting new replies while we clear them for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) (*iter)->release(); m_networkReplies.clear(); -#endif // QT_NO_NETWORK +#endif // qml_network } void QQmlTypeLoader::lock() @@ -1138,7 +1138,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) setData(blob, fileName); } else { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url)); QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy(); blob->addref(); @@ -1156,14 +1156,14 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) #ifdef DATABLOB_DEBUG qWarning("QQmlDataBlob: requested %s", qPrintable(blob->url().toString())); #endif // DATABLOB_DEBUG -#endif // QT_NO_NETWORK +#endif // qml_network } } #define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 #define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64 -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) { Q_ASSERT(m_thread->isThisThread()); @@ -1219,7 +1219,7 @@ void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply, m_thread->callDownloadProgressChanged(blob, blob->m_data.progress()); } } -#endif // QT_NO_NETWORK +#endif // qml_network /*! Return the QQmlEngine associated with this loader diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 5c779e450d..53cf4234e1 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -51,9 +51,10 @@ // We mean it. // +#include #include #include -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) #include #endif #include @@ -154,7 +155,7 @@ protected: virtual void dataReceived(const Data &) = 0; virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit*) = 0; virtual void done(); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) virtual void networkError(QNetworkReply::NetworkError); #endif virtual void dependencyError(QQmlDataBlob *); @@ -320,16 +321,16 @@ public: private: friend class QQmlDataBlob; friend class QQmlTypeLoaderThread; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) friend class QQmlTypeLoaderNetworkReplyProxy; -#endif // QT_NO_NETWORK +#endif // qml_network void shutdownThread(); void loadThread(QQmlDataBlob *); void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &); void loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) void networkReplyFinished(QNetworkReply *); void networkReplyProgress(QNetworkReply *, qint64, qint64); @@ -366,7 +367,7 @@ private: QQmlEngine *m_engine; QQmlTypeLoaderThread *m_thread; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) NetworkReplies m_networkReplies; #endif TypeCache m_typeCache; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index f94946820f..10b1cbcfd4 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -70,7 +70,7 @@ using namespace QV4; -#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK) +#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network) #define V4THROW_REFERENCE(string) { \ ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \ @@ -2056,6 +2056,6 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4) QT_END_NAMESPACE -#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK +#endif // QT_NO_XMLSTREAMREADER && qml_network #include diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h index df30873915..fdb6194537 100644 --- a/src/qml/qml/qqmlxmlhttprequest_p.h +++ b/src/qml/qml/qqmlxmlhttprequest_p.h @@ -55,7 +55,7 @@ #include #include -#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK) +#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network) QT_BEGIN_NAMESPACE @@ -64,7 +64,7 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *); QT_END_NAMESPACE -#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK +#endif // QT_NO_XMLSTREAMREADER && qml_network #endif // QQMLXMLHTTPREQUEST_P_H diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index f15020f6c9..b0599dd0a2 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -160,8 +160,10 @@ QV8Engine::~QV8Engine() qDeleteAll(m_extensionData); m_extensionData.clear(); +#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network) qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData); m_xmlHttpRequestData = 0; +#endif delete m_listModelData; m_listModelData = 0; @@ -169,7 +171,7 @@ QV8Engine::~QV8Engine() delete m_v4Engine; } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkAccessManager *QV8Engine::networkAccessManager() { return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager(); @@ -193,7 +195,7 @@ void QV8Engine::initializeGlobal() QQmlDateExtension::registerExtension(m_v4Engine); QQmlNumberExtension::registerExtension(m_v4Engine); -#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK) +#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network) qt_add_domexceptions(m_v4Engine); m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine); #endif diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 390831609b..0cbe34fd30 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -188,7 +188,7 @@ public: void freezeObject(const QV4::Value &value); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) // Return the network access manager for this engine. By default this returns the network // access manager of the QQmlEngine. It is overridden in the case of a threaded v8 // instance (like in WorkerScript). diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h index 8529e1f980..89228b7777 100644 --- a/src/qml/qtqmlglobal.h +++ b/src/qml/qtqmlglobal.h @@ -42,7 +42,9 @@ #include #include +#if QT_CONFIG(qml_network) #include +#endif QT_BEGIN_NAMESPACE diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 10666476fe..78e7776c9b 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -54,7 +54,7 @@ #include #include #include -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) #include #include "qqmlnetworkaccessmanagerfactory.h" #endif @@ -144,7 +144,7 @@ public: void init(); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) virtual QNetworkAccessManager *networkAccessManager(); #endif @@ -155,7 +155,7 @@ public: QV4::PersistentValue onmessage; private: QV4::PersistentValue createsend; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkAccessManager *accessManager; #endif }; @@ -202,7 +202,7 @@ private: QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent) : QV8Engine(0), p(parent) -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) , accessManager(0) #endif { @@ -211,7 +211,7 @@ QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEn QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) delete accessManager; #endif } @@ -274,7 +274,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i return scope.result.asReturnedValue(); } -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager() { if (!accessManager) { -- cgit v1.2.3 From 3cde2d4c24ffe6ec629077558ddc958ca6f61240 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 30 Aug 2016 16:23:16 +0200 Subject: QML: Align CompiledData::Function fields better Align all fields on an 8-byte boundary to make sure there are no bus errors or penalties for unaligned access. Change-Id: Ia455860bb0403178882b80e1036f067666386e77 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4compileddata_p.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index ae8677138e..fe18024070 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x04 +#define QV4_DATA_STRUCTURE_VERSION 0x05 class QIODevice; class QQmlPropertyCache; @@ -202,6 +202,8 @@ struct String } }; +// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties +// for unaligned access. The ordering of the fields is also from largest to smallest. struct Function { enum Flags : unsigned int { @@ -212,6 +214,11 @@ struct Function HasCatchOrWith = 0x10 }; + // Absolute offset into file where the code for this function is located. Only used when the function + // is serialized. + LEUInt64 codeOffset; + LEUInt64 codeSize; + LEUInt32 nameIndex; LEUInt32 nFormals; LEUInt32 formalsOffset; @@ -229,11 +236,6 @@ struct Function LEUInt32 dependingScopePropertiesOffset; // Array of int pairs (property index and notify index) // Qml Extensions End - // Absolute offset into file where the code for this function is located. Only used when the function - // is serialized. - LEUInt64 codeOffset; - LEUInt64 codeSize; - // quint32 formalsIndex[nFormals] // quint32 localsIndex[nLocals] // quint32 offsetForInnerFunctions[nInnerFunctions] -- cgit v1.2.3 From 60c4810c73e41e3c4b930206b9f0a5c56a2b9026 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 5 Oct 2016 16:44:31 +0200 Subject: QML: Turn DSE back on Now that all Heap::Base derived classes are trivial, we can turn dead- store elimination back on. Change-Id: I7da3aa8f3933fa9ef8a340e3114b154fc731d3ed Reviewed-by: Simon Hausmann --- src/qml/qml.pro | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/qml') diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 84c3f04349..826a074701 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -19,11 +19,6 @@ exists("qqml_enable_gcov") { LIBS_PRIVATE += -lgcov } -gcc:!intel_icc:greaterThan(QT_GCC_MAJOR_VERSION, 5) { - # Our code is bad. Temporary workaround. - QMAKE_CXXFLAGS += -fno-delete-null-pointer-checks -fno-lifetime-dse -} - # QTBUG-55238, disable new optimizer for MSVC 2015/Update 3. release:win32-msvc*:equals(QT_CL_MAJOR_VERSION, 19):equals(QT_CL_MINOR_VERSION, 00): \ greaterThan(QT_CL_PATCH_VERSION, 24212):QMAKE_CXXFLAGS += -d2SSAOptimizer- -- cgit v1.2.3 From 51a7d0331ed430d0f81d02c1b690bd12da8fdb3b Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 10 Oct 2016 12:20:44 +0200 Subject: Doc: corrected reference to category name qqmlloggingcategory.cpp:76: warning: Can't link to 'QLoggingCategory::name() Change-Id: I17311fdb6e435bd82e808c83140c2d1509f0a915 Reviewed-by: Venugopal Shivashankar --- src/qml/qml/qqmlloggingcategory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp index 88cf14cba0..fd8fb477c7 100644 --- a/src/qml/qml/qqmlloggingcategory.cpp +++ b/src/qml/qml/qqmlloggingcategory.cpp @@ -81,7 +81,7 @@ \note This property needs to be set when declaring the LoggingCategory and cannot be changed later. - \sa QLoggingCategory::name() + \sa QLoggingCategory::categoryName() */ QQmlLoggingCategory::QQmlLoggingCategory(QObject *parent) -- cgit v1.2.3 From 9d2169a2d8b81b8707b20ab892550f4a55c07feb Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 12 Oct 2016 11:15:09 +0200 Subject: V4: Fix usage of QV4::Value tags/types These two were mixed, but have completely different values. Task-number: QTBUG-56471 Change-Id: Ifbf6da3032335ea89bfbc3acde17f64a571b9dc0 Reviewed-by: Simon Hausmann --- src/qml/jit/qv4isel_masm.cpp | 6 +++--- src/qml/jsruntime/qv4arraydata.cpp | 29 +++++++++++++++++------------ src/qml/jsruntime/qv4persistent.cpp | 2 +- src/qml/jsruntime/qv4value_p.h | 19 +++++++++++++++++++ src/qml/memory/qv4mm.cpp | 2 +- 5 files changed, 41 insertions(+), 17 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 1913b398eb..05afc1ee77 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -965,7 +965,7 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target) tag = QV4::Value::Integer_Type_Internal; break; default: - tag = QV4::Value::Undefined_Type; + tag = 31337; // bogus value Q_UNREACHABLE(); } _as->store32(Assembler::TrustedImm32(tag), addr); @@ -1412,7 +1412,7 @@ void InstructionSelection::visitCJump(IR::CJump *s) Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond); Address tag = temp; tag.offset += QV4::Value::tagOffset(); - Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type)); + Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal)); Address data = temp; data.offset += QV4::Value::valueOffset(); @@ -1576,7 +1576,7 @@ void InstructionSelection::visitRet(IR::Ret *s) tag = QV4::Value::Boolean_Type_Internal; break; default: - tag = QV4::Value::Undefined_Type; + tag = 31337; // bogus value Q_UNREACHABLE(); } _as->or64(Assembler::TrustedImm64(tag << 32), diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 85d8155d3c..6316737237 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -98,7 +98,7 @@ Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData)); static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value) { Value v; - v.setTagValue(Value::fromReturnedValue(*target).tag(), value); + v.setEmpty(value); *target = v.asReturnedValue(); } @@ -187,6 +187,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } else { sparse->sparse = new SparseArray; lastFree = &sparse->freeList; + storeValue(lastFree, 0); for (uint i = 0; i < toCopy; ++i) { if (!sparse->arrayData[i].isEmpty()) { SparseArrayNode *n = sparse->sparse->insert(i); @@ -207,6 +208,8 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } storeValue(lastFree, UINT_MAX); } + + Q_ASSERT(Value::fromReturnedValue(sparse->freeList).isEmpty()); // ### Could explicitly free the old data } @@ -355,12 +358,12 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx) Value *v = d->arrayData + idx; if (d->attrs && d->attrs[idx].isAccessor()) { // double slot, free both. Order is important, so we have a double slot for allocation again afterwards. - v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value()); - v[0].setTagValue(Value::Empty_Type, idx + 1); + v[1].setEmpty(Value::fromReturnedValue(d->freeList).emptyValue()); + v[0].setEmpty(idx + 1); } else { - v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value()); + v->setEmpty(Value::fromReturnedValue(d->freeList).emptyValue()); } - d->freeList = idx; + d->freeList = Primitive::emptyValue(idx).asReturnedValue(); if (d->attrs) d->attrs[idx].clear(); } @@ -398,9 +401,9 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value()); if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) { // found two slots in a row - uint idx = Value::fromReturnedValue(*last).uint_32(); + uint idx = Value::fromReturnedValue(*last).emptyValue(); Value lastV = Value::fromReturnedValue(*last); - lastV.setTagValue(lastV.tag(), dd->arrayData[lastV.value() + 1].value()); + lastV.setEmpty(dd->arrayData[lastV.emptyValue() + 1].value()); *last = lastV.rawValue(); dd->attrs[idx] = Attr_Accessor; return idx; @@ -414,7 +417,8 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) } uint idx = Value::fromReturnedValue(dd->freeList).value(); Q_ASSERT(idx != UINT_MAX); - dd->freeList = dd->arrayData[idx].uint_32(); + dd->freeList = dd->arrayData[idx].asReturnedValue(); + Q_ASSERT(Value::fromReturnedValue(dd->freeList).isEmpty()); if (dd->attrs) dd->attrs[idx] = Attr_Data; return idx; @@ -469,13 +473,14 @@ bool SparseArrayData::del(Object *o, uint index) if (isAccessor) { // free up both indices - dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value()); - dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1); + dd->arrayData[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); + dd->arrayData[pidx].setEmpty(pidx + 1); } else { - dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value()); + Q_ASSERT(dd->type == Heap::ArrayData::Sparse); + dd->arrayData[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); } - dd->freeList = pidx; + dd->freeList = Primitive::emptyValue(pidx).asReturnedValue(); dd->sparse->erase(n); return true; } diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index fd3bd1f660..3f70a41a17 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -133,7 +133,7 @@ PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++() while (p) { while (index < kEntriesPerPage - 1) { ++index; - if (static_cast(p)->values[index].tag() != QV4::Value::Empty_Type) + if (!static_cast(p)->values[index].isEmpty()) return *this; } index = -1; diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index ebe43b505d..13339129eb 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -220,6 +220,17 @@ public: setTagValue(Empty_Type_Internal, quint32(i)); } + Q_ALWAYS_INLINE void setEmpty(quint32 i) + { + setTagValue(Empty_Type_Internal, i); + } + + Q_ALWAYS_INLINE quint32 emptyValue() + { + Q_ASSERT(isEmpty()); + return quint32(value()); + } + enum Type { Undefined_Type, Managed_Type, @@ -524,6 +535,7 @@ ReturnedValue Heap::Base::asReturnedValue() const struct Q_QML_PRIVATE_EXPORT Primitive : public Value { inline static Primitive emptyValue(); + inline static Primitive emptyValue(uint v); static inline Primitive fromBoolean(bool b); static inline Primitive fromInt32(int i); inline static Primitive undefinedValue(); @@ -553,6 +565,13 @@ inline Primitive Primitive::emptyValue() return v; } +inline Primitive Primitive::emptyValue(uint e) +{ + Primitive v; + v.setEmpty(e); + return v; +} + inline Primitive Primitive::nullValue() { Primitive v; diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 2588d8db00..b11c8c5100 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -454,7 +454,7 @@ void MemoryManager::sweep(bool lastSweep) remainingWeakQObjectWrappers.reserve(pendingCount); for (int i = 0; i < pendingCount; ++i) { Value *v = m_pendingFreedObjectWrapperValue.at(i); - if (v->tag() == Value::Undefined_Type) + if (v->isUndefined() || v->isEmpty()) PersistentValueStorage::free(v); else remainingWeakQObjectWrappers.append(v); -- cgit v1.2.3 From 330663c7b6d0faa7d10ec511d58b317a5ec37a19 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 14 Oct 2016 12:00:14 +0200 Subject: QML: Prevent unnecessary QUrl->QString->QByteArray conversions When QQmlMemoryProfiler is not used, do not convert the filename URL of a component to be converted from QUrl to a UTF8 char array. Change-Id: I741ec5b58678f3a25badac38f0198c9cff203eb1 Reviewed-by: Simon Hausmann --- src/qml/debugger/qqmlmemoryprofiler.cpp | 37 +++++++++---------------- src/qml/debugger/qqmlmemoryprofiler_p.h | 48 +++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 30 deletions(-) (limited to 'src/qml') diff --git a/src/qml/debugger/qqmlmemoryprofiler.cpp b/src/qml/debugger/qqmlmemoryprofiler.cpp index 60f6d96eaf..53d4e7ab21 100644 --- a/src/qml/debugger/qqmlmemoryprofiler.cpp +++ b/src/qml/debugger/qqmlmemoryprofiler.cpp @@ -38,18 +38,11 @@ ****************************************************************************/ #include "qqmlmemoryprofiler_p.h" -#include QT_BEGIN_NAMESPACE -enum LibraryState -{ - Unloaded, - Failed, - Loaded -}; -static LibraryState state = Unloaded; +QQmlMemoryScope::LibraryState QQmlMemoryScope::state = QQmlMemoryScope::Unloaded; typedef void (qmlmemprofile_stats)(int *allocCount, int *bytesAllocated); typedef void (qmlmemprofile_clear)(); @@ -73,7 +66,7 @@ static qmlmemprofile_is_enabled *memprofile_is_enabled; extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol); #endif -static bool openLibrary() +bool QQmlMemoryScope::doOpenLibrary() { #if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY) if (state == Unloaded) { @@ -97,28 +90,22 @@ static bool openLibrary() return state == Loaded; } -QQmlMemoryScope::QQmlMemoryScope(const QUrl &url) - : QQmlMemoryScope(url.path().toUtf8().constData()) -{ -} - -QQmlMemoryScope::QQmlMemoryScope(const char *string) : pushed(false) +void QQmlMemoryScope::init(const char *string) { - if (openLibrary() && memprofile_is_enabled()) { + if (memprofile_is_enabled()) { memprofile_push_location(string, 0); pushed = true; } } -QQmlMemoryScope::~QQmlMemoryScope() +void QQmlMemoryScope::done() { - if (pushed) - memprofile_pop_location(); + memprofile_pop_location(); } bool QQmlMemoryProfiler::isEnabled() { - if (openLibrary()) + if (QQmlMemoryScope::openLibrary()) return memprofile_is_enabled(); return false; @@ -126,31 +113,31 @@ bool QQmlMemoryProfiler::isEnabled() void QQmlMemoryProfiler::enable() { - if (openLibrary()) + if (QQmlMemoryScope::openLibrary()) memprofile_enable(); } void QQmlMemoryProfiler::disable() { - if (openLibrary()) + if (QQmlMemoryScope::openLibrary()) memprofile_disable(); } void QQmlMemoryProfiler::clear() { - if (openLibrary()) + if (QQmlMemoryScope::openLibrary()) memprofile_clear(); } void QQmlMemoryProfiler::stats(int *allocCount, int *bytesAllocated) { - if (openLibrary()) + if (QQmlMemoryScope::openLibrary()) memprofile_stats(allocCount, bytesAllocated); } void QQmlMemoryProfiler::save(const char *filename) { - if (openLibrary()) + if (QQmlMemoryScope::openLibrary()) memprofile_save(filename); } diff --git a/src/qml/debugger/qqmlmemoryprofiler_p.h b/src/qml/debugger/qqmlmemoryprofiler_p.h index 59f08704ca..fb71c999c3 100644 --- a/src/qml/debugger/qqmlmemoryprofiler_p.h +++ b/src/qml/debugger/qqmlmemoryprofiler_p.h @@ -52,6 +52,7 @@ // #include +#include QT_BEGIN_NAMESPACE @@ -62,16 +63,53 @@ QT_BEGIN_NAMESPACE #else -class QUrl; - class Q_QML_PRIVATE_EXPORT QQmlMemoryScope { public: - explicit QQmlMemoryScope(const QUrl &url); - explicit QQmlMemoryScope(const char *string); - ~QQmlMemoryScope(); + explicit QQmlMemoryScope(const QUrl &url) + : pushed(false) + { + if (Q_UNLIKELY(openLibrary())) + init(url.path().toUtf8().constData()); + } + + explicit QQmlMemoryScope(const char *string) + : pushed(false) + { + if (Q_UNLIKELY(openLibrary())) + init(string); + } + + ~QQmlMemoryScope() + { + if (Q_UNLIKELY(pushed)) + done(); + } + + enum LibraryState + { + Unloaded, + Failed, + Loaded + }; + + static bool openLibrary() + { + if (Q_LIKELY(state == Loaded)) + return true; + if (state == Failed) + return false; + + return doOpenLibrary(); + } private: + Q_NEVER_INLINE void init(const char *string); + Q_NEVER_INLINE void done(); + Q_NEVER_INLINE static bool doOpenLibrary(); + + static LibraryState state; + bool pushed; }; -- cgit v1.2.3 From a94452b1991a111ee44c298b9fdf9f63a9513ca5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 12 Sep 2016 16:48:59 +0200 Subject: Fix written time stamp in QML cache files for QRC sources For loading and verification we compare against the time stamp of the executable, so we should do the same thing when generating the cache data. Task-number: QTBUG-55926 Change-Id: If5922e76b8ae86185f6eacb6aeeb5c3afbc1f8d5 Reviewed-by: Erik Verbruggen --- src/qml/qml/qqmltypeloader.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 1f1c9d7150..333ac430d3 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -3102,8 +3102,14 @@ QByteArray QQmlDataBlob::Data::readAll(QString *error, qint64 *sourceTimeStamp) *error = f.errorString(); return QByteArray(); } - if (sourceTimeStamp) - *sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch(); + if (sourceTimeStamp) { + QDateTime timeStamp = QFileInfo(f).lastModified(); + // Files from the resource system do not have any time stamps, so fall back to the application + // executable. + if (!timeStamp.isValid()) + timeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified(); + *sourceTimeStamp = timeStamp.toMSecsSinceEpoch(); + } QByteArray data(f.size(), Qt::Uninitialized); if (f.read(data.data(), data.length()) != data.length()) { *error = f.errorString(); -- cgit v1.2.3