aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-10-10 14:49:25 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2016-10-10 14:49:25 +0000
commit8fe6b4d3ef03955c23a1d8816d4c947efbde381b (patch)
treebb077d2bfa9c2d922eb83cb386859162aa3a63c1 /src
parentbae22adafc3a6f5ff7f920e71c1542dc25cf1bab (diff)
parent102fa9b6db82ecd2b95d168912fde0c8bc3798b3 (diff)
Merge "Merge remote-tracking branch 'origin/5.7' into 5.8" into refs/staging/5.8
Diffstat (limited to 'src')
-rw-r--r--src/qml/debugger/qqmldebug.cpp18
-rw-r--r--src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc8
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc3
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/signals.qdoc3
-rw-r--r--src/qml/jit/qv4assembler.cpp38
-rw-r--r--src/qml/jit/qv4assembler_p.h5
-rw-r--r--src/qml/jit/qv4isel_masm.cpp98
-rw-r--r--src/qml/jit/qv4isel_masm_p.h4
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp13
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp14
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h2
-rw-r--r--src/qml/jsruntime/qv4value_p.h246
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp26
-rw-r--r--src/qml/memory/qv4mm.cpp9
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp7
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h14
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp12
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp32
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h1
-rw-r--r--src/quick/items/qquickflickable.cpp9
-rw-r--r--src/quick/items/qquickitem.cpp40
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h4
-rw-r--r--src/quick/items/qquickmousearea.cpp2
-rw-r--r--src/quick/items/qquickpositioners.cpp8
-rw-r--r--src/quick/items/qquickrectangle.cpp2
-rw-r--r--src/quick/items/qquicktext.cpp6
-rw-r--r--src/quick/items/qquickview.cpp26
-rw-r--r--src/quick/items/qquickview_p.h30
-rw-r--r--src/quick/items/qquickwindowmodule.cpp8
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp6
-rw-r--r--src/quick/util/qquickimageprovider.cpp4
-rw-r--r--src/quick/util/qquickpixmapcache.cpp1
36 files changed, 439 insertions, 273 deletions
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 386fb60b3a..b2c4b139ee 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -169,4 +169,22 @@ bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName,
return connector ? connector->open(configuration) : 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.
+ 2
+};
+
+Q_STATIC_ASSERT(HookCount == sizeof(qtDeclarativeHookData) / sizeof(qtDeclarativeHookData[0]));
+
QT_END_NAMESPACE
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 3692605c18..db9eee7714 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
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 5e05f14192..e1acc33f82 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -196,8 +196,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) {
@@ -210,8 +232,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) {
@@ -408,9 +433,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 7d4d90882a..94478cd9cd 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -319,6 +319,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 d06d6907e5..ecc29ba1e1 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -693,7 +693,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
}
@@ -1099,7 +1099,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
@@ -1190,10 +1190,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);
@@ -1208,7 +1213,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
generateRuntimeCall(Assembler::ReturnValueRegister, 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) {
@@ -1751,9 +1756,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;
@@ -1769,16 +1774,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;
@@ -1789,7 +1792,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);
@@ -1802,9 +1805,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;
}
@@ -1895,10 +1943,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 88241bd503..b6ddd3c1c9 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -171,8 +171,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/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 76faef137f..659ede7552 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -186,6 +186,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())
@@ -193,8 +197,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)
@@ -203,7 +206,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
QString R;
// ### FIXME
- if (ArrayObject *a = self->as<ArrayObject>()) {
+ if (ArrayObject *a = instance->as<ArrayObject>()) {
ScopedValue e(scope);
for (uint i = 0; i < a->getLength(); ++i) {
if (i)
@@ -220,7 +223,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();
@@ -229,7 +232,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();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 9636fefc14..94a6e4daa1 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -44,6 +44,7 @@
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4runtime_p.h>
+#include <qv4variantobject_p.h>
#include "qv4string_p.h"
#include <qstack.h>
@@ -734,6 +735,10 @@ QString Stringify::Str(const QString &key, const Value &v)
return std::isfinite(d) ? scope.result.toQString() : QStringLiteral("null");
}
+ if (const QV4::VariantObject *v = scope.result.as<QV4::VariantObject>()) {
+ return v->d()->data().toString();
+ }
+
o = scope.result.asReturnedValue();
if (o) {
if (!o->as<FunctionObject>()) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index fc3d147c1d..d66b5364be 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -614,8 +614,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<QV4::QObjectWrapper>(object))->asReturnedValue();
}
@@ -979,6 +985,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();
}
}
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index a32244c8de..8b2fd506e8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -77,7 +77,7 @@ namespace Heap {
struct QQmlValueTypeWrapper;
-struct QObjectWrapper : Object {
+struct Q_QML_EXPORT QObjectWrapper : Object {
void init(QObject *object);
void destroy() {
qObj.destroy();
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 44d171e087..5022d7c3bc 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -324,7 +324,7 @@ struct ScopedCallData {
{
int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value);
ptr = reinterpret_cast<CallData *>(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 6e28e21887..b87dbc5b8d 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -76,23 +76,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;
@@ -140,7 +202,7 @@ public:
{
quint32 v;
memcpy(&v, &b, 4);
- setTagValue(Managed_Type, v);
+ setTagValue(Managed_Type_Internal, v);
}
#endif
@@ -156,12 +218,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
@@ -169,101 +251,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;
@@ -509,14 +554,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;
}
@@ -544,7 +589,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;
}
@@ -562,31 +606,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 9d18713253..0f7f6b1f75 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -571,7 +571,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<QV4::CallData *>(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, engine->runtime.callValue(engine, VALUE(instr.dest), callData));
@@ -581,7 +581,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<QV4::CallData *>(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, engine->runtime.callProperty(engine, instr.name, callData));
@@ -590,7 +590,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<QV4::CallData *>(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, engine->runtime.callPropertyLookup(engine, instr.lookupIndex, callData));
@@ -600,7 +600,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<QV4::CallData *>(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, engine->runtime.callQmlScopeObjectProperty(engine, instr.index, callData));
@@ -610,7 +610,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<QV4::CallData *>(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, engine->runtime.callQmlContextObjectProperty(engine, instr.index, callData));
@@ -619,7 +619,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<QV4::CallData *>(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, engine->runtime.callElement(engine, VALUE(instr.index), callData));
@@ -628,7 +628,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<QV4::CallData *>(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, engine->runtime.callActivationProperty(engine, instr.name, callData));
@@ -637,7 +637,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<QV4::CallData *>(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::method_callGlobalLookup(engine, instr.index, callData));
@@ -743,7 +743,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<QV4::CallData *>(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, engine->runtime.constructValue(engine, VALUE(instr.func), callData));
@@ -752,7 +752,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<QV4::CallData *>(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, engine->runtime.constructProperty(engine, instr.name, callData));
@@ -761,7 +761,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<QV4::CallData *>(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, engine->runtime.constructPropertyLookup(engine, instr.index, callData));
@@ -770,7 +770,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<QV4::CallData *>(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, engine->runtime.constructActivationProperty(engine, instr.name, callData));
@@ -779,7 +779,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<QV4::CallData *>(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, engine->runtime.constructGlobalLookup(engine, instr.index, callData));
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 5aaf710ee8..edb02466ef 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -46,7 +46,7 @@
#include "PageAllocation.h"
#include "StdLibExtras.h"
-#include <QTime>
+#include <QElapsedTimer>
#include <QMap>
#include <QScopedValueRollback>
@@ -596,18 +596,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();
size_t 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.";
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 337c37b5be..f75ab9e25b 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -246,7 +246,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);
}
@@ -507,6 +507,11 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
const char *name = mci.name();
if (0 == qstrcmp(name, "DefaultProperty")) {
_defaultPropertyName = QString::fromUtf8(mci.value());
+ } else if (0 == qstrcmp(name, "qt_QmlJSWrapperFactoryMethod")) {
+ const char * const factoryMethod = mci.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 4da02037fa..18ae32ebf9 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -431,6 +431,8 @@ public:
void toMetaObjectBuilder(QMetaObjectBuilder &);
+ inline bool callJSFactoryMethod(QObject *object, void **args) const;
+
static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
@@ -505,6 +507,7 @@ private:
QByteArray _dynamicStringData;
QString _defaultPropertyName;
QQmlPropertyCacheMethodArguments *argumentsCache;
+ int _jsFactoryMethodIndex;
QByteArray _checksum;
};
@@ -806,6 +809,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()
{
}
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index ddecf7c3d4..4435c0c37b 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -548,6 +548,9 @@ QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
{
QQuickContext2DTexture::beginPainting();
+ const qreal devicePixelRatio = (m_item && m_item->window()) ?
+ m_item->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio();
+
if (m_canvasWindow.size().isEmpty()) {
delete m_fbo;
delete m_multisampledFbo;
@@ -562,7 +565,7 @@ QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
delete m_paint_device;
m_paint_device = 0;
- m_fboSize = npotAdjustedSize(m_canvasWindow.size());
+ m_fboSize = npotAdjustedSize(m_canvasWindow.size() * devicePixelRatio);
m_canvasWindowChanged = false;
if (doMultisampling()) {
@@ -600,6 +603,7 @@ QPaintDevice* QQuickContext2DFBOTexture::beginPainting()
QOpenGLPaintDevice *gl_device = new QOpenGLPaintDevice(m_fbo->size());
gl_device->setPaintFlipped(true);
gl_device->setSize(m_fbo->size());
+ gl_device->setDevicePixelRatio(devicePixelRatio);
m_paint_device = gl_device;
}
@@ -705,8 +709,12 @@ QPaintDevice* QQuickContext2DImageTexture::beginPainting()
if (m_canvasWindow.size().isEmpty())
return 0;
+ const qreal devicePixelRatio = (m_item && m_item->window()) ?
+ m_item->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio();
+
if (m_canvasWindowChanged) {
- m_image = QImage(m_canvasWindow.size(), QImage::Format_ARGB32_Premultiplied);
+ m_image = QImage(m_canvasWindow.size() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
+ m_image.setDevicePixelRatio(devicePixelRatio);
m_image.fill(0x00000000);
m_canvasWindowChanged = false;
}
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 991ca8519f..8aeef4ef4a 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -42,6 +42,7 @@
#include "qquicksprite_p.h"
#include "qquickspriteengine_p.h"
#include <QtQuick/private/qsgcontext_p.h>
+#include <QtQuick/private/qquickitem_p.h>
#include <private/qsgadaptationlayer_p.h>
#include <private/qqmlglobal_p.h>
#include <QtQuick/qsgnode.h>
@@ -349,7 +350,7 @@ void QQuickAnimatedSprite::start()
}
emit currentFrameChanged(0);
emit runningChanged(true);
- update();
+ maybeUpdate();
}
void QQuickAnimatedSprite::stop()
@@ -360,7 +361,7 @@ void QQuickAnimatedSprite::stop()
return;
d->m_pauseOffset = 0;
emit runningChanged(false);
- update();
+ maybeUpdate();
}
/*!
@@ -379,7 +380,15 @@ void QQuickAnimatedSprite::advance(int frames)
d->m_curFrame += d->m_spriteEngine->maxFrames();
d->m_curFrame = d->m_curFrame % d->m_spriteEngine->maxFrames();
emit currentFrameChanged(d->m_curFrame);
- update();
+ maybeUpdate();
+}
+
+void QQuickAnimatedSprite::maybeUpdate()
+{
+ QQuickItemPrivate *priv = QQuickItemPrivate::get(this);
+ const QLazilyAllocated<QQuickItemPrivate::ExtraData> &extraData = priv->extra;
+ if ((extraData.isAllocated() && extraData->effectRefCount > 0) || priv->effectiveVisible)
+ update();
}
/*!
@@ -399,7 +408,7 @@ void QQuickAnimatedSprite::pause()
d->m_pauseOffset = d->m_timestamp.elapsed();
d->m_paused = true;
emit pausedChanged(true);
- update();
+ maybeUpdate();
}
/*!
@@ -419,7 +428,7 @@ void QQuickAnimatedSprite::resume()
d->m_pauseOffset = d->m_pauseOffset - d->m_timestamp.elapsed();
d->m_paused = false;
emit pausedChanged(false);
- update();
+ maybeUpdate();
}
void QQuickAnimatedSprite::setRunning(bool arg)
@@ -610,7 +619,6 @@ void QQuickAnimatedSprite::createEngine()
d->m_spriteEngine = new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList), this);
d->m_spriteEngine->startAssemblingImage();
reset();
- update();
}
QSGSpriteNode* QQuickAnimatedSprite::initNode()
@@ -622,10 +630,10 @@ QSGSpriteNode* QQuickAnimatedSprite::initNode()
return nullptr;
} else if (d->m_spriteEngine->status() == QQuickPixmap::Null) {
d->m_spriteEngine->startAssemblingImage();
- update();//Schedule another update, where we will check again
+ maybeUpdate();//Schedule another update, where we will check again
return nullptr;
} else if (d->m_spriteEngine->status() == QQuickPixmap::Loading) {
- update();//Schedule another update, where we will check again
+ maybeUpdate();//Schedule another update, where we will check again
return nullptr;
}
@@ -651,7 +659,7 @@ void QQuickAnimatedSprite::reset()
{
Q_D(QQuickAnimatedSprite);
d->m_pleaseReset = true;
- update();
+ maybeUpdate();
}
QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
@@ -673,7 +681,7 @@ QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *oldNode, UpdatePaintNode
prepareNextFrame(node);
if (d->m_running && !d->m_paused)
- update();
+ maybeUpdate();
return node;
}
@@ -726,7 +734,7 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node)
frameAt = 0;
d->m_running = false;
emit runningChanged(false);
- update();
+ maybeUpdate();
}
} else {
frameAt = d->m_curFrame;
@@ -734,7 +742,7 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node)
if (d->m_curFrame != lastFrame) {
if (isCurrentFrameChangedConnected())
emit currentFrameChanged(d->m_curFrame);
- update();
+ maybeUpdate();
}
qreal frameCount = d->m_spriteEngine->spriteFrames();
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index 11cdfe11cc..850461a011 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -172,6 +172,7 @@ protected:
void componentComplete() Q_DECL_OVERRIDE;
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
private:
+ void maybeUpdate();
bool isCurrentFrameChangedConnected();
void prepareNextFrame(QSGSpriteNode *node);
void reloadImage();
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index e69c6a8d59..12b01b8aaf 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1556,11 +1556,11 @@ void QQuickFlickablePrivate::replayDelayedPress()
// If we have the grab, release before delivering the event
if (QQuickWindow *w = q->window()) {
+ replayingPressEvent = true;
if (w->mouseGrabberItem() == q)
q->ungrabMouse();
// Use the event handler that will take care of finding the proper item to propagate the event
- replayingPressEvent = true;
QCoreApplication::sendEvent(w, mouseEvent.data());
replayingPressEvent = false;
}
@@ -1590,7 +1590,7 @@ void QQuickFlickable::timerEvent(QTimerEvent *event)
d->movementEndingTimer.stop();
d->pressed = false;
d->stealMouse = false;
- if (!d->velocityTimeline.isActive())
+ if (!d->velocityTimeline.isActive() && !d->timeline.isActive())
movementEnding(true, true);
}
}
@@ -1643,7 +1643,7 @@ void QQuickFlickable::viewportMoved(Qt::Orientations orient)
void QQuickFlickablePrivate::viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
QQuickTimeLineCallback::Callback fixupCallback)
{
- if (pressed || calcVelocity) {
+ if (!scrollingPhase && (pressed || calcVelocity)) {
int elapsed = data.velocityTime.restart();
if (elapsed > 0) {
qreal velocity = (data.lastPos - data.move.value()) * 1000 / elapsed;
@@ -2216,7 +2216,8 @@ void QQuickFlickable::mouseUngrabEvent()
Q_D(QQuickFlickable);
// if our mouse grab has been removed (probably by another Flickable),
// fix our state
- d->cancelInteraction();
+ if (!d->replayingPressEvent)
+ d->cancelInteraction();
}
void QQuickFlickablePrivate::cancelInteraction()
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 63d95f6032..e219e9b34e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -7033,15 +7033,6 @@ void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
}
}
-void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e)
-{
- Q_Q(QQuickItem);
- QV4::QObjectWrapper::markWrapper(q, e);
-
- for (QQuickItem *child : qAsConst(childItems))
- QQuickItemPrivate::get(child)->markObjects(e);
-}
-
#ifndef QT_NO_CURSOR
/*!
@@ -8222,6 +8213,37 @@ QAccessible::Role QQuickItemPrivate::accessibleRole() const
}
#endif
+// helper code to let a visual parent mark its visual children for the garbage collector
+
+namespace QV4 {
+namespace Heap {
+struct QQuickItemWrapper : public QObjectWrapper {
+};
+}
+}
+
+struct QQuickItemWrapper : public QV4::QObjectWrapper {
+ V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper)
+ static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
+};
+
+DEFINE_OBJECT_VTABLE(QQuickItemWrapper);
+
+void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
+{
+ QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
+ if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
+ foreach (QQuickItem *child, QQuickItemPrivate::get(item)->childItems)
+ QV4::QObjectWrapper::markWrapper(child, e);
+ }
+ QV4::QObjectWrapper::markObjects(that, e);
+}
+
+quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine)
+{
+ return (engine->memoryManager->allocObject<QQuickItemWrapper>(q_func()))->asReturnedValue();
+}
+
QT_END_NAMESPACE
#include <moc_qquickitem.cpp>
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index 87ae83246c..510d46739a 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -148,6 +148,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus
Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL)
Q_CLASSINFO("DefaultProperty", "data")
+ Q_CLASSINFO("qt_QmlJSWrapperFactoryMethod", "_q_createJSWrapper(QV4::ExecutionEngine*)")
public:
enum Flag {
@@ -442,6 +443,7 @@ protected:
private:
Q_PRIVATE_SLOT(d_func(), void _q_resourceObjectDeleted(QObject *))
+ Q_PRIVATE_SLOT(d_func(), quint64 _q_createJSWrapper(QV4::ExecutionEngine *))
friend class QQuickWindow;
friend class QQuickWindowPrivate;
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 3bb4b2835c..4bff293657 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -305,6 +305,7 @@ public:
void _q_resourceObjectDeleted(QObject *);
void _q_windowChanged(QQuickWindow *w);
+ quint64 _q_createJSWrapper(QV4::ExecutionEngine *engine);
enum ChangeType {
Geometry = 0x01,
@@ -600,9 +601,6 @@ public:
void setHasCursorInChild(bool hasCursor);
void setHasHoverInChild(bool hasHover);
- // recursive helper to let a visual parent mark its visual children
- void markObjects(QV4::ExecutionEngine *e);
-
virtual void updatePolish() { }
};
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index b377390535..6bd83dd808 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -673,6 +673,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
Q_D(QQuickMouseArea);
d->moved = false;
d->stealMouse = d->preventStealing;
+ d->overThreshold = false;
if (!d->enabled || !(event->button() & acceptedMouseButtons())) {
QQuickItem::mousePressEvent(event);
} else {
@@ -958,6 +959,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
if (!d->pressed) {
// no other buttons are pressed
d->stealMouse = false;
+ d->overThreshold = false;
if (c && c->mouseGrabberItem() == this)
ungrabMouse();
emit canceled();
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index 38e89e78eb..e22427ca49 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -872,7 +872,7 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem)
the item that is being added. See the \l ViewTransition documentation for more details
and examples on using these transitions.
- \note This transition is not applied to the items that already part of the positioner
+ \note This transition is not applied to the items that are already part of the positioner
at the time of its creation. In this case, the \l populate transition is applied instead.
\sa populate, ViewTransition, {Qt Quick Examples - Positioners}
@@ -1039,7 +1039,7 @@ void QQuickColumn::reportConflictingAnchors()
the item that is being added. See the \l ViewTransition documentation for more details
and examples on using these transitions.
- \note This transition is not applied to the items that already part of the positioner
+ \note This transition is not applied to the items that are already part of the positioner
at the time of its creation. In this case, the \l populate transition is applied instead.
\sa populate, ViewTransition, {Qt Quick Examples - Positioners}
@@ -1307,7 +1307,7 @@ void QQuickRow::reportConflictingAnchors()
the item that is being added. See the \l ViewTransition documentation for more details
and examples on using these transitions.
- \note This transition is not applied to the items that already part of the positioner
+ \note This transition is not applied to the items that are already part of the positioner
at the time of its creation. In this case, the \l populate transition is applied instead.
\sa populate, ViewTransition, {Qt Quick Examples - Positioners}
@@ -1882,7 +1882,7 @@ void QQuickGrid::reportConflictingAnchors()
the item that is being added. See the \l ViewTransition documentation for more details
and examples on using these transitions.
- \note This transition is not applied to the items that already part of the positioner
+ \note This transition is not applied to the items that are already part of the positioner
at the time of its creation. In this case, the \l populate transition is applied instead.
\sa populate, ViewTransition, {Qt Quick Examples - Positioners}
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 9e747f2c47..7ba2421d62 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -365,7 +365,7 @@ QQuickPen *QQuickRectangle::border()
The gradient to use to fill the rectangle.
This property allows for the construction of simple vertical gradients.
- Other gradients may by formed by adding rotation to the rectangle.
+ Other gradients may be formed by adding rotation to the rectangle.
\div {class="float-left"}
\inlineimage declarative-rect_gradient.png
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 14268b472e..2bfb4501fc 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -898,11 +898,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
// If the width of the item has changed and it's possible the result of wrapping,
// eliding, scaling has changed, or the text is not left aligned do another layout.
- if ((lineWidth < qMin(oldWidth, naturalWidth) || (widthExceeded && lineWidth > oldWidth))
+ if ((!qFuzzyCompare(lineWidth, oldWidth) || (widthExceeded && lineWidth > oldWidth))
&& (singlelineElide || multilineElide || canWrap || horizontalFit
|| q->effectiveHAlign() != QQuickText::AlignLeft)) {
widthChanged = true;
- widthExceeded = false;
+ widthExceeded = lineWidth >= qMin(oldWidth, naturalWidth);
heightExceeded = false;
continue;
}
@@ -937,7 +937,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
bool wasInLayout = internalWidthUpdate;
internalWidthUpdate = true;
- q->setImplicitHeight(naturalHeight);
+ q->setImplicitHeight(naturalHeight + q->topPadding() + q->bottomPadding());
internalWidthUpdate = wasInLayout;
multilineElide = elideMode == QQuickText::ElideRight
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index d79d8ba3cd..a167f01484 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -48,29 +48,11 @@
#include <QtQml/qqmlengine.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4qobjectwrapper_p.h>
#include <QtCore/qbasictimer.h>
QT_BEGIN_NAMESPACE
-DEFINE_OBJECT_VTABLE(QV4::QQuickRootItemMarker);
-
-QV4::Heap::QQuickRootItemMarker *QV4::QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
-{
- QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine);
- return e->memoryManager->allocObject<QQuickRootItemMarker>(window);
-}
-
-void QV4::QQuickRootItemMarker::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
-{
- QQuickItem *root = static_cast<QQuickRootItemMarker::Data *>(that)->window->contentItem();
- if (root) {
- QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root);
- rootPrivate->markObjects(e);
- }
-
- QV4::Object::markObjects(that, e);
-}
-
void QQuickViewPrivate::init(QQmlEngine* e)
{
Q_Q(QQuickView);
@@ -84,10 +66,10 @@ void QQuickViewPrivate::init(QQmlEngine* e)
engine.data()->setIncubationController(q->incubationController());
{
+ // The content item has CppOwnership policy (set in QQuickWindow). Ensure the presence of a JS
+ // wrapper so that the garbage collector can see the policy.
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine.data());
- QV4::Scope scope(v4);
- QV4::Scoped<QV4::QQuickRootItemMarker> v(scope, QV4::QQuickRootItemMarker::create(engine.data(), q));
- rootItemMarker.set(v4, v);
+ QV4::QObjectWrapper::wrap(v4, contentItem);
}
}
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
index 9c0d87984f..a090bdc9f7 100644
--- a/src/quick/items/qquickview_p.h
+++ b/src/quick/items/qquickview_p.h
@@ -108,38 +108,8 @@ public:
QQuickView::ResizeMode resizeMode;
QSize initialSize;
QElapsedTimer frameTimer;
- QV4::PersistentValue rootItemMarker;
};
-namespace QV4 {
-namespace Heap {
-
-struct QQuickRootItemMarker : Object {
- inline void init(QQuickWindow *window)
- {
- Object::init();
- this->window = window;
- }
-
- QQuickWindow *window;
-};
-
-}
-
-struct QQuickRootItemMarker : public Object
-{
- V4_OBJECT2(QQuickRootItemMarker, Object)
-
- static Heap::QQuickRootItemMarker *create(QQmlEngine *engine, QQuickWindow *window);
-
- static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
-
-};
-
-
-
-}
-
QT_END_NAMESPACE
#endif // QQUICKVIEW_P_H
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index c624d162a9..deb44ce34d 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -47,6 +47,7 @@
#include <private/qguiapplication_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4qobjectwrapper_p.h>
#include <qpa/qplatformintegration.h>
QT_BEGIN_NAMESPACE
@@ -104,12 +105,11 @@ void QQuickWindowQmlImpl::classBegin()
if (e && !e->incubationController())
e->setIncubationController(incubationController());
}
- Q_ASSERT(e);
{
+ // The content item has CppOwnership policy (set in QQuickWindow). Ensure the presence of a JS
+ // wrapper so that the garbage collector can see the policy.
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(e);
- QV4::Scope scope(v4);
- QV4::ScopedObject v(scope, QV4::QQuickRootItemMarker::create(e, this));
- d->rootItemMarker = v;
+ QV4::QObjectWrapper::wrap(v4, d->contentItem);
}
}
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 688fc7db08..d52f69c7a3 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -307,10 +307,6 @@ QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
QSize QSGContext::minimumFBOSize() const
{
-#ifdef Q_OS_MAC
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_8)
- return QSize(33, 33);
-#endif
return QSize(1, 1);
}
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 6f10611ba3..1a17453baf 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -99,12 +99,12 @@ void QSGDefaultRenderContext::initialize(void *context)
#ifdef Q_OS_LINUX
const char *vendor = (const char *) funcs->glGetString(GL_VENDOR);
- if (strstr(vendor, "nouveau"))
+ if (vendor && strstr(vendor, "nouveau"))
m_brokenIBOs = true;
const char *renderer = (const char *) funcs->glGetString(GL_RENDERER);
- if (strstr(renderer, "llvmpipe"))
+ if (renderer && strstr(renderer, "llvmpipe"))
m_serializedRender = true;
- if (strstr(vendor, "Hisilicon Technologies") && strstr(renderer, "Immersion.16"))
+ if (vendor && renderer && strstr(vendor, "Hisilicon Technologies") && strstr(renderer, "Immersion.16"))
m_brokenIBOs = true;
#endif
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index 6cecf6f6f6..0c245d2b23 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -105,7 +105,7 @@ QImage QQuickTextureFactory::image() const
}
/*!
- Returns a QQuickTextureFactory holding the given image.
+ Returns a QQuickTextureFactory holding the given \a image.
This is typically used as a helper in QQuickImageResponse::textureFactory.
@@ -187,6 +187,8 @@ QString QQuickImageResponse::errorString() const
This method is used to communicate that the response is no longer required by the engine.
It may be reimplemented to cancel a request in the provider side, however, it is not mandatory.
+
+ A cancelled QQuickImageResponse still needs to emit finished().
*/
void QQuickImageResponse::cancel()
{
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 46f6cccc62..96b88636fe 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -614,7 +614,6 @@ void QQuickPixmapReader::processJobs()
if (asyncResponse) {
asyncResponses.remove(asyncResponse);
asyncResponse->cancel();
- asyncResponse->deleteLater();
}
}
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));