[SCM] qtdeclarative packaging branch, experimental, updated. debian/5.7.0-3-4-gfe1dbcb
Dmitry Shachnev
mitya57 at moszumanska.debian.org
Wed Oct 5 20:05:06 UTC 2016
Gitweb-URL: http://git.debian.org/?p=pkg-kde/qt/qtdeclarative.git;a=commitdiff;h=fe1dbcb
The following commit has been merged in the experimental branch:
commit fe1dbcb345b61e49bdee829ff8c5005e53b8fd16
Author: Dmitry Shachnev <mitya57 at gmail.com>
Date: Wed Oct 5 23:04:38 2016 +0300
Backport upstream patch to allow using 49 address bits in 64-bit mode.
This should fix issues on arm64.
---
debian/changelog | 2 +
debian/patches/series | 1 +
debian/patches/use_49_address_bits.diff | 737 ++++++++++++++++++++++++++++++++
3 files changed, 740 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index ffd8a93..34c7130 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,8 @@ qtdeclarative-opensource-src (5.7.0-4) UNRELEASED; urgency=medium
on top of the above patch.
* Add a patch to make the qqmlapplicationengine test pass when JIT is not
available (fix_tst_qqmlapplicationengine.diff, forwarded upstream).
+ * Backport upstream patch to allow using 49 address bits in 64-bit mode
+ (use_49_address_bits.diff). This should fix issues on arm64.
-- Debian Qt/KDE Maintainers <debian-qt-kde at lists.debian.org> Wed, 05 Oct 2016 22:45:29 +0300
diff --git a/debian/patches/series b/debian/patches/series
index 2431283..59eec11 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -3,6 +3,7 @@ no_lifetime_dse.diff
no_value_without_tag.diff
fix_engine_64bits_big_endian.diff
fix-V4-on-big-endian.patch
+use_49_address_bits.diff
# Forwarded upstream
fix_tst_qqmlapplicationengine.diff
diff --git a/debian/patches/use_49_address_bits.diff b/debian/patches/use_49_address_bits.diff
new file mode 100644
index 0000000..158fbb8
--- /dev/null
+++ b/debian/patches/use_49_address_bits.diff
@@ -0,0 +1,737 @@
+Description: V4: free up 2 address bits in 64bit mode
+ This allows for the OS to use 49 address bits.
+ It also maps JS Undefined to the C++ nullptr on 64bit.
+Origin: upstream, https://code.qt.io/cgit/qt/qtdeclarative.git/commit/?id=2afb54fb51091765
+Last-Update: 2016-10-05
+
+--- a/src/qml/jit/qv4assembler.cpp
++++ b/src/qml/jit/qv4assembler.cpp
+@@ -139,8 +139,30 @@
+ 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) {
+@@ -153,8 +175,11 @@
+ }
+ }
+
+-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) {
+@@ -338,9 +363,8 @@
+ // 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,
+--- a/src/qml/jit/qv4assembler_p.h
++++ b/src/qml/jit/qv4assembler_p.h
+@@ -380,6 +380,11 @@
+ 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);
+--- a/src/qml/jit/qv4isel_masm.cpp
++++ b/src/qml/jit/qv4isel_masm.cpp
+@@ -709,7 +709,7 @@
+ #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
+ }
+
+@@ -1109,7 +1109,7 @@
+ // 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
+@@ -1200,10 +1200,15 @@
+ _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);
+@@ -1218,7 +1223,7 @@
+ generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
+ _as->loadAddress(Assembler::ScratchRegister, source));
+
+- isInt.link(_as);
++ isIntConvertible.link(_as);
+ success.link(_as);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
+@@ -1790,9 +1795,9 @@
+ {
+ 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;
+@@ -1808,16 +1813,14 @@
+ }
+
+ // 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;
+@@ -1828,7 +1831,7 @@
+ }
+
+ if (IR::Const *c = varSrc->asConst()) {
+- if (c->type == nullOrUndef)
++ if (c->type == IR::NullType)
+ _as->jumpToBlock(_block, trueBlock);
+ else
+ _as->jumpToBlock(_block, falseBlock);
+@@ -1841,9 +1844,54 @@
+ _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;
+ }
+@@ -1934,10 +1982,14 @@
+ 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;
+ }
+--- a/src/qml/jit/qv4isel_masm_p.h
++++ b/src/qml/jit/qv4isel_masm_p.h
+@@ -172,8 +172,8 @@
+ 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);
+--- a/src/qml/jsruntime/qv4scopedvalue_p.h
++++ b/src/qml/jsruntime/qv4scopedvalue_p.h
+@@ -315,7 +315,7 @@
+ {
+ 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;
+ }
+
+--- a/src/qml/jsruntime/qv4value_p.h
++++ b/src/qml/jsruntime/qv4value_p.h
+@@ -76,23 +76,85 @@
+ /*
+ 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 @@
+ {
+ quint32 v;
+ memcpy(&v, &b, 4);
+- setTagValue(Managed_Type, v);
++ setTagValue(Managed_Type_Internal, v);
+ }
+ #endif
+
+@@ -156,12 +218,32 @@
+
+ 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 @@
+ 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;
+@@ -503,14 +548,14 @@
+ 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;
+ }
+
+@@ -538,7 +583,6 @@
+ inline Primitive Primitive::fromInt32(int i)
+ {
+ Primitive v;
+- v.setTagValue(Integer_Type_Internal, 0);
+ v.setInt_32(i);
+ return v;
+ }
+@@ -556,31 +600,23 @@
+
+ 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;
+--- a/src/qml/jsruntime/qv4vme_moth.cpp
++++ b/src/qml/jsruntime/qv4vme_moth.cpp
+@@ -569,7 +569,7 @@
+ #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, Runtime::callValue(engine, VALUE(instr.dest), callData));
+@@ -579,7 +579,7 @@
+ 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, Runtime::callProperty(engine, instr.name, callData));
+@@ -588,7 +588,7 @@
+ 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, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData));
+@@ -598,7 +598,7 @@
+ 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, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData));
+@@ -608,7 +608,7 @@
+ 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, Runtime::callQmlContextObjectProperty(engine, instr.index, callData));
+@@ -617,7 +617,7 @@
+ 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, Runtime::callElement(engine, VALUE(instr.index), callData));
+@@ -626,7 +626,7 @@
+ 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, Runtime::callActivationProperty(engine, instr.name, callData));
+@@ -635,7 +635,7 @@
+ 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::callGlobalLookup(engine, instr.index, callData));
+@@ -741,7 +741,7 @@
+ 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, Runtime::constructValue(engine, VALUE(instr.func), callData));
+@@ -750,7 +750,7 @@
+ 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, Runtime::constructProperty(engine, instr.name, callData));
+@@ -759,7 +759,7 @@
+ 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, Runtime::constructPropertyLookup(engine, instr.index, callData));
+@@ -768,7 +768,7 @@
+ 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, Runtime::constructActivationProperty(engine, instr.name, callData));
+@@ -777,7 +777,7 @@
+ 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, Runtime::constructGlobalLookup(engine, instr.index, callData));
--
qtdeclarative packaging
More information about the pkg-kde-commits
mailing list