aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel.cpp6
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp26
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h20
-rw-r--r--src/qml/configure.json1
-rw-r--r--src/qml/jit/qv4assembler.cpp252
-rw-r--r--src/qml/jit/qv4assembler_p.h1
-rw-r--r--src/qml/jit/qv4jit.cpp30
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h4
-rw-r--r--src/qml/jsruntime/qv4context_p.h6
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4global_p.h3
-rw-r--r--src/qml/jsruntime/qv4managed_p.h2
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h2
-rw-r--r--src/qml/jsruntime/qv4object_p.h2
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h2
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp8
-rw-r--r--src/qml/jsruntime/qv4string_p.h2
-rw-r--r--src/qml/jsruntime/qv4value_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp5
-rw-r--r--src/qml/memory/qv4heap_p.h10
-rw-r--r--src/qml/memory/qv4mm_p.h4
-rw-r--r--src/qml/memory/qv4writebarrier_p.h2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp4
-rw-r--r--src/qml/qml/v8/qv8engine_p.h10
-rw-r--r--src/qml/types/qqmllistmodel.cpp293
-rw-r--r--src/qml/types/qqmllistmodel_p.h17
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h15
-rw-r--r--src/qml/types/qqmllistmodelworkeragent.cpp89
-rw-r--r--src/qml/types/qqmllistmodelworkeragent_p.h27
-rw-r--r--src/quick/items/qquickview.cpp10
-rw-r--r--src/quick/items/qquickview.h1
-rw-r--r--src/quick/items/qquickwindow.cpp10
-rw-r--r--src/quick/items/qquickwindow.h1
-rw-r--r--src/quick/util/qquickimageprovider.h1
-rw-r--r--src/src.pro7
36 files changed, 493 insertions, 386 deletions
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
index fc9f73a881..a013e8cf69 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
@@ -1152,8 +1152,6 @@ void QQuickXmlListModel::queryCompleted(const QQuickXmlQueryResult &result)
int origCount = d->size;
bool sizeChanged = result.size != d->size;
- d->size = result.size;
- d->data = result.data;
d->keyRoleResultsCache = result.keyRoleResultsCache;
if (d->src.isEmpty() && d->xml.isEmpty())
d->status = Null;
@@ -1174,6 +1172,8 @@ void QQuickXmlListModel::queryCompleted(const QQuickXmlQueryResult &result)
beginRemoveRows(QModelIndex(), 0, origCount - 1);
endRemoveRows();
}
+ d->size = result.size;
+ d->data = result.data;
if (d->size > 0) {
beginInsertRows(QModelIndex(), 0, d->size - 1);
endInsertRows();
@@ -1187,6 +1187,8 @@ void QQuickXmlListModel::queryCompleted(const QQuickXmlQueryResult &result)
endRemoveRows();
}
}
+ d->size = result.size;
+ d->data = result.data;
for (int i=0; i<result.inserted.count(); i++) {
const int index = result.inserted[i].first;
const int count = result.inserted[i].second;
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 05bbf25292..efa4b36f05 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -76,14 +76,18 @@ void BytecodeGenerator::packInstruction(I &i)
type -= MOTH_NUM_INSTRUCTIONS();
int instructionsAsInts[sizeof(Instr)/sizeof(int)];
int nMembers = Moth::InstrInfo::argumentCount[static_cast<int>(i.type)];
- memcpy(instructionsAsInts, i.packed + 1, nMembers*sizeof(int));
+ for (int j = 0; j < nMembers; ++j) {
+ instructionsAsInts[j] = qFromLittleEndian<qint32>(i.packed + 1 + j * sizeof(int));
+ }
enum {
Normal,
Wide
} width = Normal;
for (int n = 0; n < nMembers; ++n) {
- if (width == Normal && (static_cast<char>(instructionsAsInts[n]) != instructionsAsInts[n]))
+ if (width == Normal && (static_cast<qint8>(instructionsAsInts[n]) != instructionsAsInts[n])) {
width = Wide;
+ break;
+ }
}
char *code = i.packed;
switch (width) {
@@ -91,7 +95,7 @@ void BytecodeGenerator::packInstruction(I &i)
*reinterpret_cast<uchar *>(code) = type;
++code;
for (int n = 0; n < nMembers; ++n) {
- char v = static_cast<char>(instructionsAsInts[n]);
+ qint8 v = static_cast<qint8>(instructionsAsInts[n]);
memcpy(code, &v, 1);
code += 1;
}
@@ -113,17 +117,17 @@ void BytecodeGenerator::adjustJumpOffsets()
continue;
Q_ASSERT(i.linkedLabel != -1 && labels.at(i.linkedLabel) != -1);
const auto &linkedInstruction = instructions.at(labels.at(i.linkedLabel));
- char *c = i.packed + i.offsetForJump;
+ qint8 *c = reinterpret_cast<qint8*>(i.packed + i.offsetForJump);
int jumpOffset = linkedInstruction.position - (i.position + i.size);
// qDebug() << "adjusting jump offset for instruction" << index << i.position << i.size << "offsetForJump" << i.offsetForJump << "target"
// << labels.at(i.linkedLabel) << linkedInstruction.position << "jumpOffset" << jumpOffset;
uchar type = *reinterpret_cast<const uchar *>(i.packed);
if (type >= MOTH_NUM_INSTRUCTIONS()) {
Q_ASSERT(i.offsetForJump == i.size - 4);
- memcpy(c, &jumpOffset, sizeof(int));
+ qToLittleEndian<qint32>(jumpOffset, c);
} else {
Q_ASSERT(i.offsetForJump == i.size - 1);
- char o = jumpOffset;
+ qint8 o = jumpOffset;
Q_ASSERT(o == jumpOffset);
*c = o;
}
@@ -196,7 +200,8 @@ QT_WARNING_POP
const int pos = instructions.size();
- int s = Moth::InstrInfo::argumentCount[static_cast<int>(type)]*sizeof(int);
+ const int argCount = Moth::InstrInfo::argumentCount[static_cast<int>(type)];
+ int s = argCount*sizeof(int);
if (offsetOfOffset != -1)
offsetOfOffset += 1;
I instr{type, static_cast<short>(s + 1), 0, currentLine, offsetOfOffset, -1, "\0\0" };
@@ -204,7 +209,12 @@ QT_WARNING_POP
*reinterpret_cast<uchar *>(code) = static_cast<uchar>(MOTH_NUM_INSTRUCTIONS() + static_cast<int>(type));
++code;
Q_ASSERT(MOTH_NUM_INSTRUCTIONS() + static_cast<int>(type) < 256);
- memcpy(code, &i, s);
+
+ for (int j = 0; j < argCount; ++j) {
+ qToLittleEndian<qint32>(i.argumentsAsInts[j], code);
+ code += sizeof(int);
+ }
+
instructions.append(instr);
return pos;
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index a9de71e7ad..eb25aad110 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -356,7 +356,7 @@ QT_BEGIN_NAMESPACE
nargs,
#define MOTH_DECODE_ARG(arg, type, nargs, offset) \
- arg = reinterpret_cast<const type *>(code)[-nargs + offset];
+ arg = qFromLittleEndian<type>(reinterpret_cast<const type *>(code)[-nargs + offset]);
#define MOTH_ADJUST_CODE(type, nargs) \
code += static_cast<quintptr>(nargs*sizeof(type) + 1)
@@ -366,9 +366,9 @@ QT_BEGIN_NAMESPACE
MOTH_ADJUST_CODE(int, nargs); \
MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \
goto op_main_##name; \
- op_char_##name: \
- MOTH_ADJUST_CODE(char, nargs); \
- MOTH_DECODE_ARGS(name, char, nargs, __VA_ARGS__) \
+ op_byte_##name: \
+ MOTH_ADJUST_CODE(qint8, nargs); \
+ MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \
op_main_##name: \
; \
@@ -380,10 +380,10 @@ QT_BEGIN_NAMESPACE
MOTH_ADJUST_CODE(int, nargs); \
MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \
goto op_main_##name; \
- op_char_##name: \
+ op_byte_##name: \
base_ptr = code; \
- MOTH_ADJUST_CODE(char, nargs); \
- MOTH_DECODE_ARGS(name, char, nargs, __VA_ARGS__) \
+ MOTH_ADJUST_CODE(qint8, nargs); \
+ MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \
op_main_##name: \
; \
@@ -408,7 +408,7 @@ QT_BEGIN_NAMESPACE
#define COLLECT_LABELS(instr) \
INSTR_##instr(GET_LABEL)
#define GET_LABEL_INSTRUCTION(name, ...) \
- &&op_char_##name,
+ &&op_byte_##name,
#define COLLECT_LABELS_WIDE(instr) \
INSTR_##instr(GET_LABEL_WIDE)
#define GET_LABEL_WIDE_INSTRUCTION(name, ...) \
@@ -428,7 +428,7 @@ QT_BEGIN_NAMESPACE
#define MOTH_INSTR_CASE_AND_JUMP(instr) \
INSTR_##instr(GET_CASE_AND_JUMP)
#define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \
- case static_cast<uchar>(Instr::Type::name): goto op_char_##name;
+ case static_cast<uchar>(Instr::Type::name): goto op_byte_##name;
#define MOTH_INSTR_CASE_AND_JUMP_WIDE(instr) \
INSTR_##instr(GET_CASE_AND_JUMP_WIDE)
#define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \
@@ -486,6 +486,8 @@ union Instr
FOR_EACH_MOTH_INSTR(MOTH_EMIT_STRUCTS)
FOR_EACH_MOTH_INSTR(MOTH_EMIT_INSTR_MEMBERS)
+
+ int argumentsAsInts[4];
};
struct InstrInfo
diff --git a/src/qml/configure.json b/src/qml/configure.json
index a589e9f950..723bd740fc 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -24,6 +24,7 @@
"label": "QML network support",
"purpose": "Provides network transparency.",
"section": "QML",
+ "condition": "features.network",
"output": [ "publicFeature" ]
},
"qml-debug": {
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index b0470ed89d..956ee76623 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -52,15 +52,6 @@
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
-#ifdef Q_STATIC_ASSERT_FOR_SANE_COMPILERS
-# undef Q_STATIC_ASSERT_FOR_SANE_COMPILERS
-#endif
-#if defined(Q_CC_MSVC) && _MSC_VER < 1900
-# define Q_STATIC_ASSERT_FOR_SANE_COMPILERS(x) // insane
-#else
-# define Q_STATIC_ASSERT_FOR_SANE_COMPILERS(x) Q_STATIC_ASSERT(x)
-#endif
-
#ifdef V4_ENABLE_JIT
QT_BEGIN_NAMESPACE
@@ -89,6 +80,7 @@ struct PlatformAssembler_X86_64_SysV : JSC::MacroAssembler<JSC::MacroAssemblerX8
static const RegisterID NoRegister = RegisterID(-1);
static const RegisterID ReturnValueRegister = RegisterID::eax;
+ static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
static const RegisterID AccumulatorRegister = RegisterID::eax;
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
static const RegisterID ScratchRegister = RegisterID::r10;
@@ -125,7 +117,6 @@ struct PlatformAssembler_X86_64_SysV : JSC::MacroAssembler<JSC::MacroAssemblerX8
push(EngineRegister);
move(Arg0Reg, CppStackFrameRegister);
move(Arg1Reg, EngineRegister);
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
}
void generatePlatformFunctionExit()
@@ -167,6 +158,7 @@ struct PlatformAssembler_Win64 : JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
static const RegisterID NoRegister = RegisterID(-1);
static const RegisterID ReturnValueRegister = RegisterID::eax;
+ static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
static const RegisterID AccumulatorRegister = RegisterID::eax;
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
static const RegisterID ScratchRegister = RegisterID::r10;
@@ -203,7 +195,6 @@ struct PlatformAssembler_Win64 : JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
push(EngineRegister);
move(Arg0Reg, CppStackFrameRegister);
move(Arg1Reg, EngineRegister);
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
}
void generatePlatformFunctionExit()
@@ -285,7 +276,6 @@ struct PlatformAssembler_X86_All : JSC::MacroAssembler<JSC::MacroAssemblerX86>
push(EngineRegister);
loadPtr(Address(FramePointerRegister, 2 * PointerSize), CppStackFrameRegister);
loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister);
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
}
void generatePlatformFunctionExit()
@@ -328,6 +318,7 @@ struct PlatformAssembler_ARM64 : JSC::MacroAssembler<JSC::MacroAssemblerARM64>
static const RegisterID NoRegister = RegisterID(-1);
static const RegisterID ReturnValueRegister = JSC::ARM64Registers::x0;
+ static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
static const RegisterID AccumulatorRegister = JSC::ARM64Registers::x9;
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
static const RegisterID ScratchRegister = JSC::ARM64Registers::x10;
@@ -689,6 +680,11 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
move(TrustedImm64(value), AccumulatorRegister);
}
+ void storeHeapObject(RegisterID source, Address addr)
+ {
+ store64(source, addr);
+ }
+
void generateCatchTrampoline()
{
PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();});
@@ -715,25 +711,66 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
void toNumber()
{
+ urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister);
+ auto isNumber = branch32(GreaterThanOrEqual, ScratchRegister, TrustedImm32(Value::QT_Int));
+
move(AccumulatorRegister, registerForArg(0));
callHelper(toNumberHelper);
move(ReturnValueRegister, AccumulatorRegister);
+
+ isNumber.link(this);
+ }
+
+ void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
+ {
+ load64(lhs, lhsTarget);
+ urshift64(lhsTarget, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto lhsIsInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
+ pushAligned(AccumulatorRegister);
+ move(lhsTarget, registerForArg(0));
+ callHelper(toInt32Helper);
+ move(ReturnValueRegister, lhsTarget);
+ popAligned(AccumulatorRegister);
+
+ lhsIsInt.link(this);
+ urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
+ pushAligned(lhsTarget);
+ move(AccumulatorRegister, registerForArg(0));
+ callHelper(toInt32Helper);
+ move(ReturnValueRegister, AccumulatorRegister);
+ popAligned(lhsTarget);
+
+ isInt.link(this);
}
void toInt32()
{
+ urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
move(AccumulatorRegister, registerForArg(0));
callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper),
Assembler::ResultInAccumulator);
+
+ isInt.link(this);
}
void regToInt32(Address srcReg, RegisterID targetReg)
{
+ load64(srcReg, targetReg);
+ urshift64(targetReg, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
pushAligned(AccumulatorRegister);
- load64(srcReg, registerForArg(0));
+ move(targetReg, registerForArg(0));
callHelper(toInt32Helper);
move(ReturnValueRegister, targetReg);
popAligned(AccumulatorRegister);
+
+ isInt.link(this);
}
void isNullOrUndefined()
@@ -750,6 +787,12 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
isUndef.link(this);
}
+ Jump isIntOrBool()
+ {
+ urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerOrBool_Shift), ScratchRegister);
+ return branch32(Equal, TrustedImm32(3), ScratchRegister);
+ }
+
void jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset)
{
Address lhsAddr(JSStackFrameRegister, lhs * int(sizeof(Value)));
@@ -909,6 +952,14 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
move(TrustedImm32(Value::fromReturnedValue(value).tag()), AccumulatorRegisterTag);
}
+ void storeHeapObject(RegisterID source, Address addr)
+ {
+ store32(source, addr);
+ addr.offset += 4;
+ store32(TrustedImm32(0), addr);
+ }
+
+
void generateCatchTrampoline()
{
PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();});
@@ -916,6 +967,9 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
void toNumber()
{
+ urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister);
+ auto isNumber = branch32(GreaterThanOrEqual, ScratchRegister, TrustedImm32(Value::QT_Int));
+
if (ArgInRegCount < 2) {
push(AccumulatorRegisterTag);
push(AccumulatorRegisterValue);
@@ -929,10 +983,68 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
move(ReturnValueRegisterTag, AccumulatorRegisterTag);
if (ArgInRegCount < 2)
addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+
+ isNumber.link(this);
+ }
+
+ void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
+ {
+ bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
+ || AccumulatorRegisterTag == ReturnValueRegisterTag;
+ lhs.offset += 4;
+ load32(lhs, lhsTarget);
+ lhs.offset -= 4;
+ auto lhsIsNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), lhsTarget);
+ load32(lhs, lhsTarget);
+ auto lhsIsInt = jump();
+
+ lhsIsNotInt.link(this);
+ if (accumulatorNeedsSaving) {
+ push(AccumulatorRegisterTag);
+ push(AccumulatorRegisterValue);
+ }
+ if (ArgInRegCount < 2) {
+ push(lhsTarget);
+ load32(lhs, lhsTarget);
+ push(lhsTarget);
+ } else {
+ move(lhsTarget, registerForArg(1));
+ load32(lhs, registerForArg(0));
+ }
+ callHelper(toInt32Helper);
+ move(ReturnValueRegisterValue, lhsTarget);
+ if (ArgInRegCount < 2)
+ addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+ if (accumulatorNeedsSaving) {
+ pop(AccumulatorRegisterValue);
+ pop(AccumulatorRegisterTag);
+ }
+ lhsIsInt.link(this);
+
+ auto rhsIsInt = branch32(Equal, TrustedImm32(int(IntegerTag)), AccumulatorRegisterTag);
+
+ pushAligned(lhsTarget);
+ if (ArgInRegCount < 2) {
+ push(AccumulatorRegisterTag);
+ push(AccumulatorRegisterValue);
+ } else {
+ move(AccumulatorRegisterValue, registerForArg(0));
+ move(AccumulatorRegisterTag, registerForArg(1));
+ }
+ callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper),
+ Assembler::ResultInAccumulator);
+ if (ArgInRegCount < 2)
+ addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+ popAligned(lhsTarget);
+
+ rhsIsInt.link(this);
}
void toInt32()
{
+ urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister);
+
if (ArgInRegCount < 2) {
push(AccumulatorRegisterTag);
push(AccumulatorRegisterValue);
@@ -944,6 +1056,8 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
Assembler::ResultInAccumulator);
if (ArgInRegCount < 2)
addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+
+ isInt.link(this);
}
void regToInt32(Address srcReg, RegisterID targetReg)
@@ -990,6 +1104,12 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
done.link(this);
}
+ Jump isIntOrBool()
+ {
+ urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerOrBool_Shift - 32), ScratchRegister);
+ return branch32(Equal, TrustedImm32(3), ScratchRegister);
+ }
+
void pushValue(ReturnedValue v)
{
push(TrustedImm32(v >> 32));
@@ -1321,6 +1441,11 @@ void Assembler::loadValue(ReturnedValue value)
pasm()->loadValue(value);
}
+void JIT::Assembler::storeHeapObject(int reg)
+{
+ pasm()->storeHeapObject(PlatformAssembler::ReturnValueRegisterValue, regAddr(reg));
+}
+
void Assembler::toNumber()
{
pasm()->toNumber();
@@ -1432,10 +1557,7 @@ void Assembler::add(int lhs)
void Assembler::bitAnd(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->popAligned(PlatformAssembler::ScratchRegister);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
pasm()->and32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1443,10 +1565,7 @@ void Assembler::bitAnd(int lhs)
void Assembler::bitOr(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->popAligned(PlatformAssembler::ScratchRegister);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
pasm()->or32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1454,10 +1573,7 @@ void Assembler::bitOr(int lhs)
void Assembler::bitXor(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->popAligned(PlatformAssembler::ScratchRegister);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
pasm()->xor32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1465,13 +1581,10 @@ void Assembler::bitXor(int lhs)
void Assembler::ushr(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::ScratchRegister);
- pasm()->popAligned(PlatformAssembler::AccumulatorRegisterValue);
- pasm()->urshift32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
+ pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->urshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
+ pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
PlatformAssembler::AccumulatorRegisterValue,
TrustedImm32(0));
@@ -1489,26 +1602,20 @@ void Assembler::ushr(int lhs)
void Assembler::shr(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::ScratchRegister);
- pasm()->popAligned(PlatformAssembler::AccumulatorRegisterValue);
- pasm()->rshift32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
+ pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->rshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
+ pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
void Assembler::shl(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::ScratchRegister);
- pasm()->popAligned(PlatformAssembler::AccumulatorRegisterValue);
- pasm()->lshift32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
+ pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->lshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
+ pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1537,27 +1644,32 @@ void Assembler::ushrConst(int rhs)
{
rhs &= 0x1f;
pasm()->toInt32();
- if (rhs) // shift with 0 can act weird
+ if (rhs) {
+ // a non zero shift will always give a number encodable as an int
pasm()->urshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
- auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
- PlatformAssembler::AccumulatorRegisterValue,
- TrustedImm32(0));
- pasm()->setAccumulatorTag(IntegerTag);
- auto done = pasm()->jump();
+ pasm()->setAccumulatorTag(IntegerTag);
+ } else {
+ // shift with 0 can lead to a negative result
+ auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
+ PlatformAssembler::AccumulatorRegisterValue,
+ TrustedImm32(0));
+ pasm()->setAccumulatorTag(IntegerTag);
+ auto done = pasm()->jump();
- doubleEncode.link(pasm());
- pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::FPScratchRegister,
- PlatformAssembler::ScratchRegister);
- pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
- done.link(pasm());
+ doubleEncode.link(pasm());
+ pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
+ PlatformAssembler::FPScratchRegister,
+ PlatformAssembler::ScratchRegister);
+ pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
+ done.link(pasm());
+ }
}
void Assembler::shrConst(int rhs)
{
rhs &= 0x1f;
pasm()->toInt32();
- if (rhs) // shift with 0 can act weird
+ if (rhs)
pasm()->rshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1566,7 +1678,7 @@ void Assembler::shlConst(int rhs)
{
rhs &= 0x1f;
pasm()->toInt32();
- if (rhs) // shift with 0 can act weird
+ if (rhs)
pasm()->lshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1652,6 +1764,7 @@ void Assembler::cmpneNull()
void Assembler::cmpeqInt(int lhs)
{
+ auto isIntOrBool = pasm()->isIntOrBool();
saveAccumulatorInFrame();
pasm()->pushValueAligned(Encode(lhs));
if (PlatformAssembler::ArgInRegCount < 2)
@@ -1663,10 +1776,18 @@ void Assembler::cmpeqInt(int lhs)
if (PlatformAssembler::ArgInRegCount < 2)
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
pasm()->popValueAligned();
+ auto done = pasm()->jump();
+ isIntOrBool.link(pasm());
+ pasm()->compare32(PlatformAssembler::Equal, PlatformAssembler::AccumulatorRegisterValue,
+ TrustedImm32(lhs),
+ PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
+ done.link(pasm());
}
void Assembler::cmpneInt(int lhs)
{
+ auto isIntOrBool = pasm()->isIntOrBool();
saveAccumulatorInFrame();
pasm()->pushValueAligned(Encode(lhs));
if (PlatformAssembler::ArgInRegCount < 2)
@@ -1678,6 +1799,13 @@ void Assembler::cmpneInt(int lhs)
if (PlatformAssembler::ArgInRegCount < 2)
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
pasm()->popValueAligned();
+ auto done = pasm()->jump();
+ isIntOrBool.link(pasm());
+ pasm()->compare32(PlatformAssembler::NotEqual, PlatformAssembler::AccumulatorRegisterValue,
+ TrustedImm32(lhs),
+ PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
+ done.link(pasm());
}
void Assembler::cmp(int cond, CmpFunc function, const char *functionName, int lhs)
@@ -1956,7 +2084,7 @@ void Assembler::gotoCatchException()
void Assembler::getException()
{
- Q_STATIC_ASSERT_FOR_SANE_COMPILERS(sizeof(QV4::EngineBase::hasException) == 1);
+ Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1);
Address hasExceptionAddr(PlatformAssembler::EngineRegister,
offsetof(EngineBase, hasException));
@@ -1981,7 +2109,7 @@ void Assembler::setException()
pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister);
pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister));
addr.offset = offsetof(EngineBase, hasException);
- Q_STATIC_ASSERT_FOR_SANE_COMPILERS(sizeof(QV4::EngineBase::hasException) == 1);
+ Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1);
pasm()->store8(TrustedImm32(1), addr);
}
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 5cd64096b1..37d4232a17 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -95,6 +95,7 @@ public:
void storeLocal(int index, int level = 0);
void loadString(int stringId);
void loadValue(ReturnedValue value);
+ void storeHeapObject(int reg);
// numeric ops
void unot();
diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp
index 42ee1ff5df..1ab45d6765 100644
--- a/src/qml/jit/qv4jit.cpp
+++ b/src/qml/jit/qv4jit.cpp
@@ -570,17 +570,12 @@ void BaselineJIT::generate_ThrowException()
void BaselineJIT::generate_GetException() { as->getException(); }
void BaselineJIT::generate_SetException() { as->setException(); }
-static void createCallContextHelper(Value *stack, CppStackFrame *frame)
-{
- stack[CallData::Context] = ExecutionContext::newCallContext(frame);
-}
-
void BaselineJIT::generate_CreateCallContext()
{
- as->prepareCallWithArgCount(2);
- as->passCppFrameAsArg(1);
- as->passRegAsArg(0, 0);
- JIT_GENERATE_RUNTIME_CALL(createCallContextHelper, Assembler::IgnoreResult);
+ as->prepareCallWithArgCount(1);
+ as->passCppFrameAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(ExecutionContext::newCallContext, Assembler::IgnoreResult); // keeps result in return value register
+ as->storeHeapObject(CallData::Context);
}
void BaselineJIT::generate_PushCatchContext(int name, int reg) { as->pushCatchContext(name, reg); }
@@ -951,6 +946,11 @@ void BaselineJIT::collectLabelsInBytecode()
{
MOTH_JUMP_TABLE;
+ const auto addLabel = [&](int offset) {
+ Q_ASSERT(offset >= 0 && offset < static_cast<int>(function->compiledFunction->codeSize));
+ labels.push_back(offset);
+ };
+
const char *code = reinterpret_cast<const char *>(function->codeData);
const char *start = code;
const char *end = code + function->compiledFunction->codeSize;
@@ -1088,7 +1088,7 @@ void BaselineJIT::collectLabelsInBytecode()
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(SetExceptionHandler)
- labels.push_back(code - start + offset);
+ addLabel(code - start + offset);
MOTH_END_INSTR(SetExceptionHandler)
MOTH_BEGIN_INSTR(ThrowException)
@@ -1155,15 +1155,15 @@ void BaselineJIT::collectLabelsInBytecode()
MOTH_END_INSTR(Construct)
MOTH_BEGIN_INSTR(Jump)
- labels.push_back(code - start + offset);
+ addLabel(code - start + offset);
MOTH_END_INSTR(Jump)
MOTH_BEGIN_INSTR(JumpTrue)
- labels.push_back(code - start + offset);
+ addLabel(code - start + offset);
MOTH_END_INSTR(JumpTrue)
MOTH_BEGIN_INSTR(JumpFalse)
- labels.push_back(code - start + offset);
+ addLabel(code - start + offset);
MOTH_END_INSTR(JumpFalse)
MOTH_BEGIN_INSTR(CmpEqNull)
@@ -1209,11 +1209,11 @@ void BaselineJIT::collectLabelsInBytecode()
MOTH_END_INSTR(CmpInstanceOf)
MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
- labels.push_back(code - start + offset);
+ addLabel(code - start + offset);
MOTH_END_INSTR(JumpStrictEqualStackSlotInt)
MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
- labels.push_back(code - start + offset);
+ addLabel(code - start + offset);
MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
MOTH_BEGIN_INSTR(UNot)
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index db9db5a220..46986c5e6f 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -142,7 +142,7 @@ DECLARE_HEAP_OBJECT(ArrayData, Base) {
uint mappedIndex(uint index) const;
};
-V4_ASSERT_IS_TRIVIAL(ArrayData)
+Q_STATIC_ASSERT(std::is_trivial< ArrayData >::value);
struct SimpleArrayData : public ArrayData {
uint mappedIndex(uint index) const { index += offset; if (index >= values.alloc) index -= values.alloc; return index; }
@@ -157,7 +157,7 @@ struct SimpleArrayData : public ArrayData {
return attrs ? attrs[i] : Attr_Data;
}
};
-V4_ASSERT_IS_TRIVIAL(SimpleArrayData)
+Q_STATIC_ASSERT(std::is_trivial< SimpleArrayData >::value);
struct SparseArrayData : public ArrayData {
void destroy() {
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 4efd0bc899..dfac5534be 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -143,7 +143,7 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
quint8 padding_[4];
#endif
};
-V4_ASSERT_IS_TRIVIAL(ExecutionContext)
+Q_STATIC_ASSERT(std::is_trivial< ExecutionContext >::value);
Q_STATIC_ASSERT(sizeof(ExecutionContext) == sizeof(Base) + sizeof(ExecutionContextData) + QT_POINTER_SIZE);
Q_STATIC_ASSERT(std::is_standard_layout<ExecutionContextData>::value);
@@ -170,7 +170,7 @@ DECLARE_HEAP_OBJECT(CallContext, ExecutionContext) {
}
void setArg(uint index, Value v);
};
-V4_ASSERT_IS_TRIVIAL(CallContext)
+Q_STATIC_ASSERT(std::is_trivial< CallContext >::value);
Q_STATIC_ASSERT(std::is_standard_layout<CallContextData>::value);
Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0);
//### The following size check fails on Win8. With the ValueArray at the end of the
@@ -190,7 +190,7 @@ DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) {
void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
};
-V4_ASSERT_IS_TRIVIAL(CatchContext)
+Q_STATIC_ASSERT(std::is_trivial< CatchContext >::value);
}
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index b8392d27e9..d56db80c3f 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -328,7 +328,7 @@ static inline double DaylightSavingTA(double t) // t is a UTC time
static inline double DaylightSavingTA(double t)
{
struct tm tmtm;
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#if defined(Q_CC_MSVC)
__time64_t tt = (__time64_t)(t / msPerSecond);
// _localtime_64_s returns non-zero on failure
if (_localtime64_s(&tmtm, &tt) != 0)
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 090a164ef6..07c88a2814 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -76,9 +76,6 @@ namespace std {
inline bool isinf(double d) { return !_finite(d) && !_isnan(d); }
inline bool isnan(double d) { return !!_isnan(d); }
inline bool isfinite(double d) { return _finite(d); }
-#if _MSC_VER < 1800
-inline bool signbit(double d) { return _copysign(1.0, d) < 0; }
-#endif
} // namespace std
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index f81dcf9479..092c61b81c 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -93,7 +93,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
dptr->_checkIsInitialized(); \
return dptr; \
} \
- V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass)
+ Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
#define V4_MANAGED(DataClass, superClass) \
private: \
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 3e231d693b..7345790ac3 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -65,7 +65,7 @@ namespace Heap {
DECLARE_HEAP_OBJECT(MemberData, Base) {
DECLARE_MARKOBJECTS(MemberData);
};
-V4_ASSERT_IS_TRIVIAL(MemberData)
+Q_STATIC_ASSERT(std::is_trivial< MemberData >::value);
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 66177617f7..60012822d8 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -153,7 +153,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
dptr->_checkIsInitialized(); \
return dptr; \
} \
- V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass);
+ Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
#define V4_PROTOTYPE(p) \
static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 30a6ad3025..3e501f23ce 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -73,7 +73,7 @@ struct Q_QML_EXPORT ObjectIteratorData
uint memberIndex;
uint flags;
};
-V4_ASSERT_IS_TRIVIAL(ObjectIteratorData)
+Q_STATIC_ASSERT(std::is_trivial< ObjectIteratorData >::value);
struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData
{
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 498468e165..94bebbd931 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -100,7 +100,7 @@ struct RegExp : Base {
int captureCount() const { return subPatternCount + 1; }
};
-V4_ASSERT_IS_TRIVIAL(RegExp)
+Q_STATIC_ASSERT(std::is_trivial< RegExp >::value);
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 240fba7905..93d538127b 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -604,6 +604,14 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine,
return o->get(name);
}
+/* load element:
+
+ Managed *m = object.heapObject();
+ if (m)
+ return m->internalClass->getIndexed(m, index);
+ return getIndexedFallback(object, index);
+*/
+
ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index)
{
uint idx = 0;
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 85345aca4d..9053d9d48f 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -131,7 +131,7 @@ private:
static void append(const String *data, QChar *ch);
#endif
};
-V4_ASSERT_IS_TRIVIAL(String)
+Q_STATIC_ASSERT(std::is_trivial< String >::value);
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 52d9f23afd..a0495cca61 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -483,7 +483,7 @@ public:
template<typename T>
Value &operator=(const Scoped<T> &t);
};
-V4_ASSERT_IS_TRIVIAL(Value)
+Q_STATIC_ASSERT(std::is_trivial< Value >::value);
inline void Value::mark(MarkStack *markStack)
{
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 6956112718..91558ba103 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -1142,14 +1142,13 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
MOTH_BEGIN_INSTR(CmpInstanceOf)
// 11.8.6, 5: rval must be an Object
- const Object *rhs = Primitive::fromReturnedValue(acc).as<Object>();
- if (Q_UNLIKELY(!rhs)) {
+ if (Q_UNLIKELY(!Primitive::fromReturnedValue(acc).isObject())) {
acc = engine->throwTypeError();
goto catchException;
}
// 11.8.6, 7: call "HasInstance", which we term instanceOf, and return the result.
- acc = rhs->instanceOf(STACK_VALUE(lhs));
+ acc = Primitive::fromReturnedValue(acc).objectValue()->instanceOf(STACK_VALUE(lhs));
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpInstanceOf)
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index 363e891d5c..7bc841b21d 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -60,12 +60,6 @@
// 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 {
@@ -175,7 +169,7 @@ struct Q_QML_EXPORT Base {
Q_ALWAYS_INLINE void _setDestroyed() {}
#endif
};
-V4_ASSERT_IS_TRIVIAL(Base)
+Q_STATIC_ASSERT(std::is_trivial< Base >::value);
// This class needs to consist only of pointer sized members to allow
// for a size/offset translation when cross-compiling between 32- and
// 64-bit.
@@ -253,7 +247,7 @@ private:
QtSharedPointer::ExternalRefCountData *d;
QObject *qObject;
};
-V4_ASSERT_IS_TRIVIAL(QQmlQPointer<QObject>)
+Q_STATIC_ASSERT(std::is_trivial< QQmlQPointer<QObject> >::value);
#endif
}
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 921fea3956..f7c50ff3cf 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -169,7 +169,7 @@ public:
template<typename ManagedType>
inline typename ManagedType::Data *allocManaged(std::size_t size)
{
- V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data)
+ Q_STATIC_ASSERT(std::is_trivial< typename ManagedType::Data >::value);
size = align(size);
Heap::Base *o = allocData(size);
InternalClass *ic = ManagedType::defaultInternalClass(engine);
@@ -182,7 +182,7 @@ public:
template<typename ManagedType>
inline typename ManagedType::Data *allocManaged(std::size_t size, InternalClass *ic)
{
- V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data)
+ Q_STATIC_ASSERT(std::is_trivial< typename ManagedType::Data >::value);
size = align(size);
Heap::Base *o = allocData(size);
o->internalClass = ic;
diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h
index c0f4b0b29a..39413a6f09 100644
--- a/src/qml/memory/qv4writebarrier_p.h
+++ b/src/qml/memory/qv4writebarrier_p.h
@@ -138,7 +138,7 @@ private:
Heap::Base *ptr;
};
typedef Pointer<char *, 0> V4PointerCheck;
-V4_ASSERT_IS_TRIVIAL(V4PointerCheck)
+Q_STATIC_ASSERT(std::is_trivial< V4PointerCheck >::value);
}
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index dadff819cf..2947f7870a 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -127,7 +127,6 @@ QV8Engine::QV8Engine(QJSEngine* qq)
: q(qq)
, m_engine(0)
, m_xmlHttpRequestData(0)
- , m_listModelData(0)
{
#ifdef Q_PROCESSOR_X86_32
if (!qCpuHasFeature(SSE2)) {
@@ -164,9 +163,6 @@ QV8Engine::~QV8Engine()
m_xmlHttpRequestData = 0;
#endif
- delete m_listModelData;
- m_listModelData = 0;
-
delete m_v4Engine;
}
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index a430fba0e6..98b182147c 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -77,12 +77,6 @@ namespace QV4 {
struct QObjectMethod;
}
-#define V4THROW_ERROR(string) \
- return ctx->engine()->throwError(QString::fromUtf8(string));
-
-#define V4THROW_TYPE(string) \
- return ctx->engine()->throwTypeError(QStringLiteral(string));
-
#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
{ \
@@ -183,9 +177,6 @@ public:
void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
- Deletable *listModelData() const { return m_listModelData; }
- void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
-
void freezeObject(const QV4::Value &value);
#if QT_CONFIG(qml_network)
@@ -222,7 +213,6 @@ protected:
void *m_xmlHttpRequestData;
QVector<Deletable *> m_extensionData;
- Deletable *m_listModelData;
QSet<QString> m_illegalNames;
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index e32e0c75f3..0f04d48bf8 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -271,23 +271,24 @@ QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementInde
return e->m_objectCache;
}
-void ListModel::sync(ListModel *src, ListModel *target, QHash<int, ListModel *> *targetModelHash)
+bool ListModel::sync(ListModel *src, ListModel *target)
{
// Sanity check
target->m_uid = src->m_uid;
- if (targetModelHash)
- targetModelHash->insert(target->m_uid, target);
+
+ bool hasChanges = false;
// Build hash of elements <-> uid for each of the lists
QHash<int, ElementSync> elementHash;
- for (int i=0 ; i < target->elements.count() ; ++i) {
+ for (int i = 0; i < target->elements.count(); ++i) {
ListElement *e = target->elements.at(i);
int uid = e->getUid();
ElementSync sync;
sync.target = e;
+ sync.targetIndex = i;
elementHash.insert(uid, sync);
}
- for (int i=0 ; i < src->elements.count() ; ++i) {
+ for (int i = 0; i < src->elements.count(); ++i) {
ListElement *e = src->elements.at(i);
int uid = e->getUid();
@@ -295,24 +296,39 @@ void ListModel::sync(ListModel *src, ListModel *target, QHash<int, ListModel *>
if (it == elementHash.end()) {
ElementSync sync;
sync.src = e;
+ sync.srcIndex = i;
elementHash.insert(uid, sync);
} else {
ElementSync &sync = it.value();
sync.src = e;
+ sync.srcIndex = i;
}
}
+ QQmlListModel *targetModel = target->m_modelCache;
+
// Get list of elements that are in the target but no longer in the source. These get deleted first.
- QHash<int, ElementSync>::iterator it = elementHash.begin();
- QHash<int, ElementSync>::iterator end = elementHash.end();
- while (it != end) {
- const ElementSync &s = it.value();
- if (s.src == 0) {
+ int rowsRemoved = 0;
+ for (int i = 0 ; i < target->elements.count() ; ++i) {
+ ListElement *element = target->elements.at(i);
+ ElementSync &s = elementHash.find(element->getUid()).value();
+ Q_ASSERT(s.targetIndex >= 0);
+ // need to update the targetIndex, to keep it correct after removals
+ s.targetIndex -= rowsRemoved;
+ if (s.src == nullptr) {
+ Q_ASSERT(s.targetIndex == i);
+ hasChanges = true;
+ if (targetModel)
+ targetModel->beginRemoveRows(QModelIndex(), i, i);
s.target->destroy(target->m_layout);
target->elements.removeOne(s.target);
delete s.target;
+ if (targetModel)
+ targetModel->endRemoveRows();
+ ++rowsRemoved;
+ --i;
+ continue;
}
- ++it;
}
// Sync the layouts
@@ -320,15 +336,15 @@ void ListModel::sync(ListModel *src, ListModel *target, QHash<int, ListModel *>
// Clear the target list, and append in correct order from the source
target->elements.clear();
- for (int i=0 ; i < src->elements.count() ; ++i) {
+ for (int i = 0; i < src->elements.count(); ++i) {
ListElement *srcElement = src->elements.at(i);
- it = elementHash.find(srcElement->getUid());
- const ElementSync &s = it.value();
+ ElementSync &s = elementHash.find(srcElement->getUid()).value();
+ Q_ASSERT(s.srcIndex >= 0);
ListElement *targetElement = s.target;
- if (targetElement == 0) {
+ if (targetElement == nullptr) {
targetElement = new ListElement(srcElement->getUid());
}
- ListElement::sync(srcElement, src->m_layout, targetElement, target->m_layout, targetModelHash);
+ s.changedRoles = ListElement::sync(srcElement, src->m_layout, targetElement, target->m_layout);
target->elements.append(targetElement);
}
@@ -340,6 +356,39 @@ void ListModel::sync(ListModel *src, ListModel *target, QHash<int, ListModel *>
if (ModelNodeMetaObject *mo = e->objectCache())
mo->updateValues();
}
+
+ // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
+ // so the model indices can't be out of bounds
+ //
+ // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
+ // model indices are updated correctly
+ int rowsInserted = 0;
+ for (int i = 0 ; i < target->elements.count() ; ++i) {
+ ListElement *element = target->elements.at(i);
+ ElementSync &s = elementHash.find(element->getUid()).value();
+ Q_ASSERT(s.srcIndex >= 0);
+ s.srcIndex += rowsInserted;
+ if (s.srcIndex != s.targetIndex) {
+ if (targetModel) {
+ if (s.targetIndex == -1) {
+ targetModel->beginInsertRows(QModelIndex(), i, i);
+ targetModel->endInsertRows();
+ } else {
+ targetModel->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
+ targetModel->endMoveRows();
+ }
+ }
+ hasChanges = true;
+ ++rowsInserted;
+ }
+ if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
+ QModelIndex idx = targetModel->createIndex(i, 0);
+ if (targetModel)
+ targetModel->dataChanged(idx, idx, s.changedRoles);
+ hasChanges = true;
+ }
+ }
+ return hasChanges;
}
ListModel::ListModel(ListLayout *layout, QQmlListModel *modelCache, int uid) : m_layout(layout), m_modelCache(modelCache)
@@ -949,7 +998,11 @@ int ListElement::setVariantMapProperty(const ListLayout::Role &role, QVariantMap
char *mem = getPropertyMemory(role);
if (isMemoryUsed<QVariantMap>(mem)) {
QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
+ if (m && map->isSharedWith(*m))
+ return roleIndex;
map->~QMap();
+ } else if (!m) {
+ return roleIndex;
}
if (m)
new (mem) QVariantMap(*m);
@@ -1101,12 +1154,14 @@ ListElement::~ListElement()
delete next;
}
-void ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout, QHash<int, ListModel *> *targetModelHash)
+QVector<int> ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout)
{
+ QVector<int> changedRoles;
for (int i=0 ; i < srcLayout->roleCount() ; ++i) {
const ListLayout::Role &srcRole = srcLayout->getExistingRole(i);
const ListLayout::Role &targetRole = targetLayout->getExistingRole(i);
+ int roleIndex = -1;
switch (srcRole.type) {
case ListLayout::Role::List:
{
@@ -1118,14 +1173,15 @@ void ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *tar
targetSubModel = new ListModel(targetRole.subLayout, 0, srcSubModel->getUid());
target->setListPropertyFast(targetRole, targetSubModel);
}
- ListModel::sync(srcSubModel, targetSubModel, targetModelHash);
+ if (ListModel::sync(srcSubModel, targetSubModel))
+ roleIndex = targetRole.index;
}
}
break;
case ListLayout::Role::QObject:
{
QObject *object = src->getQObjectProperty(srcRole);
- target->setQObjectProperty(targetRole, object);
+ roleIndex = target->setQObjectProperty(targetRole, object);
}
break;
case ListLayout::Role::String:
@@ -1135,20 +1191,23 @@ void ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *tar
case ListLayout::Role::Function:
{
QVariant v = src->getProperty(srcRole, 0, 0);
- target->setVariantProperty(targetRole, v);
+ roleIndex = target->setVariantProperty(targetRole, v);
}
break;
case ListLayout::Role::VariantMap:
{
QVariantMap *map = src->getVariantMapProperty(srcRole);
- target->setVariantMapProperty(targetRole, map);
+ roleIndex = target->setVariantMapProperty(targetRole, map);
}
break;
default:
break;
}
+ if (roleIndex >= 0)
+ changedRoles << roleIndex;
}
+ return changedRoles;
}
void ListElement::destroy(ListLayout *layout)
@@ -1493,20 +1552,22 @@ DynamicRoleModelNode *DynamicRoleModelNode::create(const QVariantMap &obj, QQmlL
return object;
}
-void DynamicRoleModelNode::sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target, QHash<int, QQmlListModel *> *targetModelHash)
+QVector<int> DynamicRoleModelNode::sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target)
{
- for (int i=0 ; i < src->m_meta->count() ; ++i) {
+ QVector<int> changedRoles;
+ for (int i = 0; i < src->m_meta->count(); ++i) {
const QByteArray &name = src->m_meta->name(i);
QVariant value = src->m_meta->value(i);
QQmlListModel *srcModel = qobject_cast<QQmlListModel *>(value.value<QObject *>());
QQmlListModel *targetModel = qobject_cast<QQmlListModel *>(target->m_meta->value(i).value<QObject *>());
+ bool modelHasChanges = false;
if (srcModel) {
if (targetModel == 0)
targetModel = QQmlListModel::createWithOwner(target->m_owner);
- QQmlListModel::sync(srcModel, targetModel, targetModelHash);
+ modelHasChanges = QQmlListModel::sync(srcModel, targetModel);
QObject *targetModelObject = targetModel;
value = QVariant::fromValue(targetModelObject);
@@ -1514,8 +1575,10 @@ void DynamicRoleModelNode::sync(DynamicRoleModelNode *src, DynamicRoleModelNode
delete targetModel;
}
- target->setValue(name, value);
+ if (target->setValue(name, value) || modelHasChanges)
+ changedRoles << target->m_owner->m_roles.indexOf(QString::fromUtf8(name));
}
+ return changedRoles;
}
void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int> &roles)
@@ -1761,9 +1824,9 @@ QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agen
m_listModel = new ListModel(m_layout, this, orig->m_listModel->getUid());
if (m_dynamicRoles)
- sync(orig, this, 0);
+ sync(orig, this);
else
- ListModel::sync(orig->m_listModel, m_listModel, 0);
+ ListModel::sync(orig->m_listModel, m_listModel);
m_engine = 0;
}
@@ -1814,25 +1877,26 @@ QV4::ExecutionEngine *QQmlListModel::engine() const
return m_engine;
}
-void QQmlListModel::sync(QQmlListModel *src, QQmlListModel *target, QHash<int, QQmlListModel *> *targetModelHash)
+bool QQmlListModel::sync(QQmlListModel *src, QQmlListModel *target)
{
Q_ASSERT(src->m_dynamicRoles && target->m_dynamicRoles);
+ bool hasChanges = false;
+
target->m_uid = src->m_uid;
- if (targetModelHash)
- targetModelHash->insert(target->m_uid, target);
target->m_roles = src->m_roles;
// Build hash of elements <-> uid for each of the lists
QHash<int, ElementSync> elementHash;
- for (int i=0 ; i < target->m_modelObjects.count() ; ++i) {
+ for (int i = 0 ; i < target->m_modelObjects.count(); ++i) {
DynamicRoleModelNode *e = target->m_modelObjects.at(i);
int uid = e->getUid();
ElementSync sync;
sync.target = e;
+ sync.targetIndex = i;
elementHash.insert(uid, sync);
}
- for (int i=0 ; i < src->m_modelObjects.count() ; ++i) {
+ for (int i = 0 ; i < src->m_modelObjects.count(); ++i) {
DynamicRoleModelNode *e = src->m_modelObjects.at(i);
int uid = e->getUid();
@@ -1840,118 +1904,102 @@ void QQmlListModel::sync(QQmlListModel *src, QQmlListModel *target, QHash<int, Q
if (it == elementHash.end()) {
ElementSync sync;
sync.src = e;
+ sync.srcIndex = i;
elementHash.insert(uid, sync);
} else {
ElementSync &sync = it.value();
sync.src = e;
+ sync.srcIndex = i;
}
}
// Get list of elements that are in the target but no longer in the source. These get deleted first.
- QHash<int, ElementSync>::iterator it = elementHash.begin();
- QHash<int, ElementSync>::iterator end = elementHash.end();
- while (it != end) {
- const ElementSync &s = it.value();
- if (s.src == 0) {
- int targetIndex = target->m_modelObjects.indexOf(s.target);
- target->m_modelObjects.remove(targetIndex, 1);
+ int rowsRemoved = 0;
+ for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
+ DynamicRoleModelNode *element = target->m_modelObjects.at(i);
+ ElementSync &s = elementHash.find(element->getUid()).value();
+ Q_ASSERT(s.targetIndex >= 0);
+ // need to update the targetIndex, to keep it correct after removals
+ s.targetIndex -= rowsRemoved;
+ if (s.src == nullptr) {
+ Q_ASSERT(s.targetIndex == i);
+ hasChanges = true;
+ target->beginRemoveRows(QModelIndex(), i, i);
+ target->m_modelObjects.remove(i, 1);
+ target->endRemoveRows();
delete s.target;
+ ++rowsRemoved;
+ --i;
+ continue;
}
- ++it;
}
// Clear the target list, and append in correct order from the source
target->m_modelObjects.clear();
- for (int i=0 ; i < src->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *srcElement = src->m_modelObjects.at(i);
- it = elementHash.find(srcElement->getUid());
- const ElementSync &s = it.value();
+ for (int i = 0 ; i < src->m_modelObjects.count() ; ++i) {
+ DynamicRoleModelNode *element = src->m_modelObjects.at(i);
+ ElementSync &s = elementHash.find(element->getUid()).value();
+ Q_ASSERT(s.srcIndex >= 0);
DynamicRoleModelNode *targetElement = s.target;
if (targetElement == 0) {
- targetElement = new DynamicRoleModelNode(target, srcElement->getUid());
+ targetElement = new DynamicRoleModelNode(target, element->getUid());
}
- DynamicRoleModelNode::sync(srcElement, targetElement, targetModelHash);
+ s.changedRoles = DynamicRoleModelNode::sync(element, targetElement);
target->m_modelObjects.append(targetElement);
}
-}
-void QQmlListModel::emitItemsChanged(int index, int count, const QVector<int> &roles)
-{
- if (count <= 0)
- return;
-
- if (m_mainThread) {
- emit dataChanged(createIndex(index, 0), createIndex(index + count - 1, 0), roles);;
- } else {
- int uid = m_dynamicRoles ? getUid() : m_listModel->getUid();
- m_agent->data.changedChange(uid, index, count, roles);
+ // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
+ // so the model indices can't be out of bounds
+ //
+ // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
+ // model indices are updated correctly
+ int rowsInserted = 0;
+ for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
+ DynamicRoleModelNode *element = target->m_modelObjects.at(i);
+ ElementSync &s = elementHash.find(element->getUid()).value();
+ Q_ASSERT(s.srcIndex >= 0);
+ s.srcIndex += rowsInserted;
+ if (s.srcIndex != s.targetIndex) {
+ if (s.targetIndex == -1) {
+ target->beginInsertRows(QModelIndex(), i, i);
+ target->endInsertRows();
+ } else {
+ target->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
+ target->endMoveRows();
+ }
+ hasChanges = true;
+ ++rowsInserted;
+ }
+ if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
+ QModelIndex idx = target->createIndex(i, 0);
+ emit target->dataChanged(idx, idx, s.changedRoles);
+ hasChanges = true;
+ }
}
+ return hasChanges;
}
-void QQmlListModel::emitItemsAboutToBeRemoved(int index, int count)
-{
- if (count <= 0 || !m_mainThread)
- return;
-
- beginRemoveRows(QModelIndex(), index, index + count - 1);
-}
-
-void QQmlListModel::emitItemsRemoved(int index, int count)
+void QQmlListModel::emitItemsChanged(int index, int count, const QVector<int> &roles)
{
if (count <= 0)
return;
- if (m_mainThread) {
- endRemoveRows();
- emit countChanged();
- } else {
- int uid = m_dynamicRoles ? getUid() : m_listModel->getUid();
- if (index == 0 && count == this->count())
- m_agent->data.clearChange(uid);
- m_agent->data.removeChange(uid, index, count);
- }
+ if (m_mainThread)
+ emit dataChanged(createIndex(index, 0), createIndex(index + count - 1, 0), roles);;
}
void QQmlListModel::emitItemsAboutToBeInserted(int index, int count)
{
- if (count <= 0 || !m_mainThread)
- return;
-
- beginInsertRows(QModelIndex(), index, index + count - 1);
+ Q_ASSERT(index >= 0 && count >= 0);
+ if (m_mainThread)
+ beginInsertRows(QModelIndex(), index, index + count - 1);
}
-void QQmlListModel::emitItemsInserted(int index, int count)
+void QQmlListModel::emitItemsInserted()
{
- if (count <= 0)
- return;
-
if (m_mainThread) {
endInsertRows();
emit countChanged();
- } else {
- int uid = m_dynamicRoles ? getUid() : m_listModel->getUid();
- m_agent->data.insertChange(uid, index, count);
- }
-}
-
-void QQmlListModel::emitItemsAboutToBeMoved(int from, int to, int n)
-{
- if (n <= 0 || !m_mainThread)
- return;
-
- beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);
-}
-
-void QQmlListModel::emitItemsMoved(int from, int to, int n)
-{
- if (n <= 0)
- return;
-
- if (m_mainThread) {
- endMoveRows();
- } else {
- int uid = m_dynamicRoles ? getUid() : m_listModel->getUid();
- m_agent->data.moveChange(uid, from, n, to);
}
}
@@ -2133,7 +2181,13 @@ void QQmlListModel::remove(QQmlV4Function *args)
void QQmlListModel::removeElements(int index, int removeCount)
{
- emitItemsAboutToBeRemoved(index, removeCount);
+ Q_ASSERT(index >= 0 && removeCount >= 0);
+
+ if (!removeCount)
+ return;
+
+ if (m_mainThread)
+ beginRemoveRows(QModelIndex(), index, index + removeCount - 1);
QVector<std::function<void()>> toDestroy;
if (m_dynamicRoles) {
@@ -2148,7 +2202,10 @@ void QQmlListModel::removeElements(int index, int removeCount)
toDestroy = m_listModel->remove(index, removeCount);
}
- emitItemsRemoved(index, removeCount);
+ if (m_mainThread) {
+ endRemoveRows();
+ emit countChanged();
+ }
for (const auto &destroyer : toDestroy)
destroyer();
}
@@ -2197,7 +2254,7 @@ void QQmlListModel::insert(QQmlV4Function *args)
m_listModel->insert(index+i, argObject);
}
}
- emitItemsInserted(index, objectArrayLength);
+ emitItemsInserted();
} else if (argObject) {
emitItemsAboutToBeInserted(index, 1);
@@ -2207,7 +2264,7 @@ void QQmlListModel::insert(QQmlV4Function *args)
m_listModel->insert(index, argObject);
}
- emitItemsInserted(index, 1);
+ emitItemsInserted();
} else {
qmlWarning(this) << tr("insert: value is not an object");
}
@@ -2232,14 +2289,15 @@ void QQmlListModel::insert(QQmlV4Function *args)
*/
void QQmlListModel::move(int from, int to, int n)
{
- if (n==0 || from==to)
+ if (n == 0 || from == to)
return;
if (!canMove(from, to, n)) {
qmlWarning(this) << tr("move: out of range");
return;
}
- emitItemsAboutToBeMoved(from, to, n);
+ if (m_mainThread)
+ beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);
if (m_dynamicRoles) {
@@ -2268,7 +2326,8 @@ void QQmlListModel::move(int from, int to, int n)
m_listModel->move(from, to, n);
}
- emitItemsMoved(from, to, n);
+ if (m_mainThread)
+ endMoveRows();
}
/*!
@@ -2308,7 +2367,7 @@ void QQmlListModel::append(QQmlV4Function *args)
}
}
- emitItemsInserted(index, objectArrayLength);
+ emitItemsInserted();
} else if (argObject) {
int index;
@@ -2322,7 +2381,7 @@ void QQmlListModel::append(QQmlV4Function *args)
m_listModel->append(argObject);
}
- emitItemsInserted(index, 1);
+ emitItemsInserted();
} else {
qmlWarning(this) << tr("append: value is not an object");
}
@@ -2424,7 +2483,7 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle)
m_listModel->insert(index, object);
}
- emitItemsInserted(index, 1);
+ emitItemsInserted();
} else {
QVector<int> roles;
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 499a113504..18b7b8bb22 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -147,24 +147,21 @@ private:
struct ElementSync
{
- ElementSync() : src(0), target(0) {}
-
- DynamicRoleModelNode *src;
- DynamicRoleModelNode *target;
+ DynamicRoleModelNode *src = nullptr;
+ DynamicRoleModelNode *target = nullptr;
+ int srcIndex = -1;
+ int targetIndex = -1;
+ QVector<int> changedRoles;
};
int getUid() const { return m_uid; }
- static void sync(QQmlListModel *src, QQmlListModel *target, QHash<int, QQmlListModel *> *targetModelHash);
+ static bool sync(QQmlListModel *src, QQmlListModel *target);
static QQmlListModel *createWithOwner(QQmlListModel *newOwner);
void emitItemsChanged(int index, int count, const QVector<int> &roles);
- void emitItemsAboutToBeRemoved(int index, int count);
- void emitItemsRemoved(int index, int count);
void emitItemsAboutToBeInserted(int index, int count);
- void emitItemsInserted(int index, int count);
- void emitItemsAboutToBeMoved(int from, int to, int n);
- void emitItemsMoved(int from, int to, int n);
+ void emitItemsInserted();
void removeElements(int index, int removeCount);
};
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index dea1ef2eb3..65567ab69a 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -108,7 +108,7 @@ public:
return m_uid;
}
- static void sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target, QHash<int, QQmlListModel *> *targetModelHash);
+ static QVector<int> sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target);
private:
QQmlListModel *m_owner;
@@ -261,7 +261,7 @@ public:
ListElement(int existingUid);
~ListElement();
- static void sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout, QHash<int, ListModel *> *targetModelHash);
+ static QVector<int> sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout);
enum
{
@@ -379,7 +379,7 @@ public:
int getUid() const { return m_uid; }
- static void sync(ListModel *src, ListModel *target, QHash<int, ListModel *> *srcModelHash);
+ static bool sync(ListModel *src, ListModel *target);
QObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
@@ -392,10 +392,11 @@ private:
struct ElementSync
{
- ElementSync() : src(0), target(0) {}
-
- ListElement *src;
- ListElement *target;
+ ListElement *src = nullptr;
+ ListElement *target = nullptr;
+ int srcIndex = -1;
+ int targetIndex = -1;
+ QVector<int> changedRoles;
};
void newElement(int index);
diff --git a/src/qml/types/qqmllistmodelworkeragent.cpp b/src/qml/types/qqmllistmodelworkeragent.cpp
index 0a5adbf292..a2750c926a 100644
--- a/src/qml/types/qqmllistmodelworkeragent.cpp
+++ b/src/qml/types/qqmllistmodelworkeragent.cpp
@@ -50,39 +50,8 @@
QT_BEGIN_NAMESPACE
-
-void QQmlListModelWorkerAgent::Data::clearChange(int uid)
-{
- for (int i=0 ; i < changes.count() ; ++i) {
- if (changes[i].modelUid == uid) {
- changes.removeAt(i);
- --i;
- }
- }
-}
-
-void QQmlListModelWorkerAgent::Data::insertChange(int uid, int index, int count)
+QQmlListModelWorkerAgent::Sync::~Sync()
{
- Change c = { uid, Change::Inserted, index, count, 0, QVector<int>() };
- changes << c;
-}
-
-void QQmlListModelWorkerAgent::Data::removeChange(int uid, int index, int count)
-{
- Change c = { uid, Change::Removed, index, count, 0, QVector<int>() };
- changes << c;
-}
-
-void QQmlListModelWorkerAgent::Data::moveChange(int uid, int index, int count, int to)
-{
- Change c = { uid, Change::Moved, index, count, to, QVector<int>() };
- changes << c;
-}
-
-void QQmlListModelWorkerAgent::Data::changedChange(int uid, int index, int count, const QVector<int> &roles)
-{
- Change c = { uid, Change::Changed, index, count, 0, roles };
- changes << c;
}
QQmlListModelWorkerAgent::QQmlListModelWorkerAgent(QQmlListModel *model)
@@ -167,8 +136,7 @@ void QQmlListModelWorkerAgent::move(int from, int to, int count)
void QQmlListModelWorkerAgent::sync()
{
- Sync *s = new Sync(data, m_copy);
- data.changes.clear();
+ Sync *s = new Sync(m_copy);
mutex.lock();
QCoreApplication::postEvent(this, s);
@@ -183,61 +151,14 @@ bool QQmlListModelWorkerAgent::event(QEvent *e)
QMutexLocker locker(&mutex);
if (m_orig) {
Sync *s = static_cast<Sync *>(e);
- const QList<Change> &changes = s->data.changes;
- cc = m_orig->count() != s->list->count();
-
- QHash<int, QQmlListModel *> targetModelDynamicHash;
- QHash<int, ListModel *> targetModelStaticHash;
+ cc = (m_orig->count() != s->list->count());
Q_ASSERT(m_orig->m_dynamicRoles == s->list->m_dynamicRoles);
if (m_orig->m_dynamicRoles)
- QQmlListModel::sync(s->list, m_orig, &targetModelDynamicHash);
+ QQmlListModel::sync(s->list, m_orig);
else
- ListModel::sync(s->list->m_listModel, m_orig->m_listModel, &targetModelStaticHash);
-
- for (int ii = 0; ii < changes.count(); ++ii) {
- const Change &change = changes.at(ii);
-
- QQmlListModel *model = 0;
- if (m_orig->m_dynamicRoles) {
- model = targetModelDynamicHash.value(change.modelUid);
- } else {
- ListModel *lm = targetModelStaticHash.value(change.modelUid);
- if (lm)
- model = lm->m_modelCache;
- }
-
- if (model) {
- switch (change.type) {
- case Change::Inserted:
- model->beginInsertRows(
- QModelIndex(), change.index, change.index + change.count - 1);
- model->endInsertRows();
- break;
- case Change::Removed:
- model->beginRemoveRows(
- QModelIndex(), change.index, change.index + change.count - 1);
- model->endRemoveRows();
- break;
- case Change::Moved:
- model->beginMoveRows(
- QModelIndex(),
- change.index,
- change.index + change.count - 1,
- QModelIndex(),
- change.to > change.index ? change.to + change.count : change.to);
- model->endMoveRows();
- break;
- case Change::Changed:
- emit model->dataChanged(
- model->createIndex(change.index, 0),
- model->createIndex(change.index + change.count - 1, 0),
- change.roles);
- break;
- }
- }
- }
+ ListModel::sync(s->list->m_listModel, m_orig->m_listModel);
}
syncDone.wakeAll();
diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h
index 5a39651bf7..761a467e89 100644
--- a/src/qml/types/qqmllistmodelworkeragent_p.h
+++ b/src/qml/types/qqmllistmodelworkeragent_p.h
@@ -114,35 +114,12 @@ private:
friend class QQuickWorkerScriptEnginePrivate;
friend class QQmlListModel;
- struct Change
- {
- int modelUid;
- enum { Inserted, Removed, Moved, Changed } type;
- int index; // Inserted/Removed/Moved/Changed
- int count; // Inserted/Removed/Moved/Changed
- int to; // Moved
- QVector<int> roles;
- };
-
- struct Data
- {
- QList<Change> changes;
-
- void clearChange(int uid);
- void insertChange(int uid, int index, int count);
- void removeChange(int uid, int index, int count);
- void moveChange(int uid, int index, int count, int to);
- void changedChange(int uid, int index, int count, const QVector<int> &roles);
- };
- Data data;
-
struct Sync : public QEvent {
- Sync(const Data &d, QQmlListModel *l)
+ Sync(QQmlListModel *l)
: QEvent(QEvent::User)
- , data(d)
, list(l)
{}
- Data data;
+ ~Sync();
QQmlListModel *list;
};
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index fca1805fc9..9a29d6c2ca 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -198,6 +198,16 @@ QQuickView::QQuickView(QQmlEngine* engine, QWindow *parent)
}
/*!
+ \internal
+*/
+QQuickView::QQuickView(const QUrl &source, QQuickRenderControl *control)
+ : QQuickWindow(*(new QQuickViewPrivate), control)
+{
+ d_func()->init();
+ setSource(source);
+}
+
+/*!
Destroys the QQuickView.
*/
QQuickView::~QQuickView()
diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h
index 014d02e7f5..006a691387 100644
--- a/src/quick/items/qquickview.h
+++ b/src/quick/items/qquickview.h
@@ -62,6 +62,7 @@ public:
explicit QQuickView(QWindow *parent = nullptr);
QQuickView(QQmlEngine* engine, QWindow *parent);
explicit QQuickView(const QUrl &source, QWindow *parent = nullptr);
+ QQuickView(const QUrl &source, QQuickRenderControl *renderControl);
virtual ~QQuickView();
QUrl source() const;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index db7a80ee9a..436adf8c49 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1288,7 +1288,15 @@ QQuickWindow::QQuickWindow(QQuickRenderControl *control)
d->init(this, control);
}
-
+/*!
+ \internal
+*/
+QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
+ : QWindow(dd, 0)
+{
+ Q_D(QQuickWindow);
+ d->init(this, control);
+}
/*!
Destroys the window.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index e5b54c8fb9..06af7bbf02 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -204,6 +204,7 @@ public Q_SLOTS:
protected:
QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent = nullptr);
+ QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control);
void exposeEvent(QExposeEvent *) override;
void resizeEvent(QResizeEvent *) override;
diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h
index 681de4b6c2..4451105782 100644
--- a/src/quick/util/qquickimageprovider.h
+++ b/src/quick/util/qquickimageprovider.h
@@ -56,6 +56,7 @@ class QQuickWindow;
class Q_QUICK_EXPORT QQuickTextureFactory : public QObject
{
+ Q_OBJECT
public:
QQuickTextureFactory();
virtual ~QQuickTextureFactory();
diff --git a/src/src.pro b/src/src.pro
index 42bf90e092..33c47048b5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -2,7 +2,7 @@ TEMPLATE = subdirs
CONFIG += ordered
include($$OUT_PWD/qml/qtqml-config.pri)
include($$OUT_PWD/quick/qtquick-config.pri)
-QT_FOR_CONFIG += network qml quick-private
+QT_FOR_CONFIG += qml quick-private
SUBDIRS += \
qml
@@ -21,4 +21,7 @@ SUBDIRS += \
imports \
qmldevtools
-qtConfig(localserver):qtConfig(qml-debug): SUBDIRS += qmldebug
+qtConfig(qml-network) {
+ QT_FOR_CONFIG += network
+ qtConfig(localserver):qtConfig(qml-debug): SUBDIRS += qmldebug
+}