aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Carr2016-09-06 13:30:39 -0700
committerDonald Carr2016-09-06 13:42:04 -0700
commit435654e04fd47e83a723e7b9aed891794615544d (patch)
treeed363ba9932ff98e872ba445a0a3573ab0b15e7c
parentfca7d208bd6f552765f4d011d8295b1a51bb0a60 (diff)
downloadaur-435654e04fd47e83a723e7b9aed891794615544d.tar.gz
Introduce WIP VA_48 patch
Change-Id: I71a5a8750dca2de43ddde8c7829e9ef281e93939
-rw-r--r--0001-WIP-V4-Free-up-2-address-bits-in-64bit-mode.patch543
-rw-r--r--PKGBUILD6
2 files changed, 547 insertions, 2 deletions
diff --git a/0001-WIP-V4-Free-up-2-address-bits-in-64bit-mode.patch b/0001-WIP-V4-Free-up-2-address-bits-in-64bit-mode.patch
new file mode 100644
index 000000000000..b186da1844b2
--- /dev/null
+++ b/0001-WIP-V4-Free-up-2-address-bits-in-64bit-mode.patch
@@ -0,0 +1,543 @@
+From 7268834eddd02930b2cf0ce06316f175d3276b0f Mon Sep 17 00:00:00 2001
+From: Erik Verbruggen <erik.verbruggen@digia.com>
+Date: Thu, 1 Sep 2016 15:34:57 +0200
+Subject: [PATCH] WIP: V4: Free up 2 address bits in 64bit mode.
+
+This allows for the OS to use 49 address bits. It also maps JS Undefined
+to the C++ nullptr on 64bit.
+
+Task-number: QTBUG-54822
+Change-Id: I7cc90620f499be1506a61aac77d72d067308838c
+---
+ src/qml/jit/qv4assembler.cpp | 38 +++++++--
+ src/qml/jit/qv4assembler_p.h | 5 ++
+ src/qml/jit/qv4isel_masm.cpp | 85 ++++++++++++++-----
+ src/qml/jit/qv4isel_masm_p.h | 4 +-
+ src/qml/jsruntime/qv4value_p.h | 184 ++++++++++++++++++-----------------------
+ 5 files changed, 184 insertions(+), 132 deletions(-)
+
+diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
+index 929726f..b7dbc81 100644
+--- a/src/qml/jit/qv4assembler.cpp
++++ b/src/qml/jit/qv4assembler.cpp
+@@ -133,8 +133,30 @@ void Assembler::generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBl
+ generateCJumpOnCompare(NotEqual, reg, TrustedImm32(0), currentBlock, trueBlock, falseBlock);
+ }
+
+-void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left,TrustedImm32 right,
+- IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
++#ifdef QV4_USE_64_BIT_VALUE_ENCODING
++void Assembler::generateCJumpOnCompare(RelationalCondition cond,
++ RegisterID left,
++ TrustedImm64 right,
++ IR::BasicBlock *currentBlock,
++ IR::BasicBlock *trueBlock,
++ IR::BasicBlock *falseBlock)
++{
++ if (trueBlock == _nextBlock) {
++ Jump target = branch64(invert(cond), left, right);
++ addPatch(falseBlock, target);
++ } else {
++ Jump target = branch64(cond, left, right);
++ addPatch(trueBlock, target);
++ jumpToBlock(currentBlock, falseBlock);
++ }
++}
++#endif
++
++void Assembler::generateCJumpOnCompare(RelationalCondition cond,
++ RegisterID left,
++ TrustedImm32 right,
++ IR::BasicBlock *currentBlock,
++ IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+ {
+ if (trueBlock == _nextBlock) {
+@@ -147,8 +169,11 @@ void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left
+ }
+ }
+
+-void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left, RegisterID right,
+- IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
++void Assembler::generateCJumpOnCompare(RelationalCondition cond,
++ RegisterID left,
++ RegisterID right,
++ IR::BasicBlock *currentBlock,
++ IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock)
+ {
+ if (trueBlock == _nextBlock) {
+@@ -334,9 +359,8 @@ Assembler::Jump Assembler::genTryDoubleConversion(IR::Expr *src, Assembler::FPRe
+ // not an int, check if it's a double:
+ isNoInt.link(this);
+ #ifdef QV4_USE_64_BIT_VALUE_ENCODING
+- and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
+- Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister,
+- Assembler::TrustedImm32(0));
++ rshift32(TrustedImm32(Value::IsDoubleTag_Shift), ScratchRegister);
++ Assembler::Jump isNoDbl = branch32(Equal, ScratchRegister, TrustedImm32(0));
+ #else
+ and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
+ Assembler::Jump isNoDbl = branch32(Assembler::Equal, Assembler::ScratchRegister,
+diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
+index 532a311..ba9ca66 100644
+--- a/src/qml/jit/qv4assembler_p.h
++++ b/src/qml/jit/qv4assembler_p.h
+@@ -374,6 +374,11 @@ public:
+ void addPatch(DataLabelPtr patch, IR::BasicBlock *target);
+ void generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBlock,
+ IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
++#ifdef QV4_USE_64_BIT_VALUE_ENCODING
++ void generateCJumpOnCompare(RelationalCondition cond, RegisterID left, TrustedImm64 right,
++ IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
++ IR::BasicBlock *falseBlock);
++#endif
+ void generateCJumpOnCompare(RelationalCondition cond, RegisterID left, TrustedImm32 right,
+ IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock,
+ IR::BasicBlock *falseBlock);
+diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
+index b6df5fb..cfd0862 100644
+--- a/src/qml/jit/qv4isel_masm.cpp
++++ b/src/qml/jit/qv4isel_masm.cpp
+@@ -703,7 +703,7 @@ void InstructionSelection::loadString(const QString &str, IR::Expr *target)
+ #else
+ _as->store32(Assembler::ReturnValueRegister, destAddr);
+ destAddr.offset += 4;
+- _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type), destAddr);
++ _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type_Internal), destAddr);
+ #endif
+ }
+
+@@ -1103,7 +1103,7 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe
+ // not an int, check if it's NOT a double:
+ isNoInt.link(_as);
+ #ifdef QV4_USE_64_BIT_VALUE_ENCODING
+- _as->and32(Assembler::TrustedImm32(Value::IsDouble_Mask), Assembler::ScratchRegister);
++ _as->rshift32(Assembler::TrustedImm32(Value::IsDoubleTag_Shift), Assembler::ScratchRegister);
+ Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+ Assembler::TrustedImm32(0));
+ #else
+@@ -1194,10 +1194,12 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
+ _as->load64(addr, Assembler::ScratchRegister);
+ _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+
+- // check if it's a number
+- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ScratchRegister);
+- Assembler::Jump isInt = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(1));
+- Assembler::Jump fallback = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
++ // check if it's integer convertible
++ _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsManagedOrUndefined_Shift), Assembler::ScratchRegister);
++ Assembler::Jump isIntConvertible = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(3));
++
++ // nope, not integer convertible, so check for a double:
++ Assembler::Jump fallback = _as->branch32(Assembler::LessThan, Assembler::ScratchRegister, Assembler::TrustedImm32(3));
+
+ // it's a double
+ _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
+@@ -1212,7 +1214,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
+ generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
+ _as->loadAddress(Assembler::ScratchRegister, source));
+
+- isInt.link(_as);
++ isIntConvertible.link(_as);
+ success.link(_as);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
+@@ -1784,9 +1786,9 @@ void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *tr
+ {
+ Q_ASSERT(binop->op == IR::OpStrictEqual || binop->op == IR::OpStrictNotEqual);
+
+- if (visitCJumpStrictNullUndefined(IR::NullType, binop, trueBlock, falseBlock))
++ if (visitCJumpStrictNull(binop, trueBlock, falseBlock))
+ return;
+- if (visitCJumpStrictNullUndefined(IR::UndefinedType, binop, trueBlock, falseBlock))
++ if (visitCJumpStrictUndefined(binop, trueBlock, falseBlock))
+ return;
+ if (visitCJumpStrictBool(binop, trueBlock, falseBlock))
+ return;
+@@ -1802,16 +1804,14 @@ void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *tr
+ }
+
+ // Only load the non-null temp.
+-bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+- IR::BasicBlock *trueBlock,
+- IR::BasicBlock *falseBlock)
++bool InstructionSelection::visitCJumpStrictNull(IR::Binop *binop,
++ IR::BasicBlock *trueBlock,
++ IR::BasicBlock *falseBlock)
+ {
+- Q_ASSERT(nullOrUndef == IR::NullType || nullOrUndef == IR::UndefinedType);
+-
+ IR::Expr *varSrc = 0;
+- if (binop->left->type == IR::VarType && binop->right->type == nullOrUndef)
++ if (binop->left->type == IR::VarType && binop->right->type == IR::NullType)
+ varSrc = binop->left;
+- else if (binop->left->type == nullOrUndef && binop->right->type == IR::VarType)
++ else if (binop->left->type == IR::NullType && binop->right->type == IR::VarType)
+ varSrc = binop->right;
+ if (!varSrc)
+ return false;
+@@ -1822,7 +1822,7 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I
+ }
+
+ if (IR::Const *c = varSrc->asConst()) {
+- if (c->type == nullOrUndef)
++ if (c->type == IR::NullType)
+ _as->jumpToBlock(_block, trueBlock);
+ else
+ _as->jumpToBlock(_block, falseBlock);
+@@ -1835,9 +1835,54 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I
+ _as->load32(tagAddr, tagReg);
+
+ Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
+- : Assembler::NotEqual;
+- const Assembler::TrustedImm32 tag(nullOrUndef == IR::NullType ? int(QV4::Value::Null_Type_Internal)
+- : int(QV4::Value::Undefined_Type));
++ : Assembler::NotEqual;
++ const Assembler::TrustedImm32 tag(QV4::Value::Null_Type_Internal);
++ _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
++ return true;
++}
++
++bool InstructionSelection::visitCJumpStrictUndefined(IR::Binop *binop,
++ IR::BasicBlock *trueBlock,
++ IR::BasicBlock *falseBlock)
++{
++ IR::Expr *varSrc = 0;
++ if (binop->left->type == IR::VarType && binop->right->type == IR::UndefinedType)
++ varSrc = binop->left;
++ else if (binop->left->type == IR::UndefinedType && binop->right->type == IR::VarType)
++ varSrc = binop->right;
++ if (!varSrc)
++ return false;
++
++ if (varSrc->asTemp() && varSrc->asTemp()->kind == IR::Temp::PhysicalRegister) {
++ _as->jumpToBlock(_block, falseBlock);
++ return true;
++ }
++
++ if (IR::Const *c = varSrc->asConst()) {
++ if (c->type == IR::UndefinedType)
++ _as->jumpToBlock(_block, trueBlock);
++ else
++ _as->jumpToBlock(_block, falseBlock);
++ return true;
++ }
++
++ Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
++ : Assembler::NotEqual;
++ const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
++#ifdef QV4_USE_64_BIT_VALUE_ENCODING
++ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
++ _as->load64(addr, tagReg);
++ const Assembler::TrustedImm64 tag(0);
++#else // !QV4_USE_64_BIT_VALUE_ENCODING
++ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
++ _as->load32(tagAddr, tagReg);
++ Assembler::Jump j = _as->branch32(Assembler::invert(cond), tagReg, Assembler::TrustedImm32(0));
++ _as->addPatch(falseBlock, j);
++
++ tagAddr.offset += 4;
++ _as->load32(tagAddr, tagReg);
++ const Assembler::TrustedImm32 tag(QV4::Value::Managed_Type_Internal);
++#endif
+ _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
+ return true;
+ }
+diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
+index 6e9b02b..f6d9364 100644
+--- a/src/qml/jit/qv4isel_masm_p.h
++++ b/src/qml/jit/qv4isel_masm_p.h
+@@ -166,8 +166,8 @@ protected:
+ bool visitCJumpSInt32(IR::AluOp op, IR::Expr *left, IR::Expr *right,
+ IR::BasicBlock *iftrue, IR::BasicBlock *iffalse);
+ void visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+- bool visitCJumpStrictNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+- IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
++ bool visitCJumpStrictNull(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
++ bool visitCJumpStrictUndefined(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+ bool visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+ bool visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+ IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
+diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
+index 5abf5ad..78d535e 100644
+--- a/src/qml/jsruntime/qv4value_p.h
++++ b/src/qml/jsruntime/qv4value_p.h
+@@ -70,23 +70,27 @@ private:
+ /*
+ We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
+
+- In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double NaN (actually -qNaN)
+- is indicated by a number that has the top 13 bits set. The other values are usually set to 0 by the
+- processor, and are thus free for us to store other data. We keep pointers in there for managed objects,
+- and encode the other types using the free space given to use by the unused bits for NaN values. This also
+- works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory.
+-
+- On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that
+- will make the number a NaN. The Masks below are used for encoding the other types.
+-
+- On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will get encoded
+- with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These
+- can be used, as the highest valid pointer on a 64 bit system is 2^48-1.
+-
+- If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer.
+- This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set).
+-
+- Bit 15-17 is then used to encode other immediates.
++ In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double
++ NaN (actually -qNaN) is indicated by a number that has the top 13 bits set, and for a
++ signalling NaN it is the top 14 bits. The other values are usually set to 0 by the
++ processor, and are thus free for us to store other data. We keep pointers in there for
++ managed objects, and encode the other types using the free space given to use by the unused
++ bits for NaN values. This also works for pointers on 64 bit systems, as they all currently
++ only have 48 bits of addressable memory. (Note: we do leave the lower 49 bits available for
++ pointers.)
++
++ On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value
++ that will make the number a NaN. The Masks below are used for encoding the other types.
++
++ On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will
++ get encoded with bits 63-49 all set to 0. We then use bit 48 to distinguish between
++ managed/undefined (0), or Null/Int/Bool/Empty (1). So, storing a 49 bit pointer will leave
++ the top 15 bits 0, which is exactly the 'natural' representation of pointers. If bit 49 is
++ set, bit 48 indicates Empty (0) or integer-convertible (1). Then the 3 bit below that are
++ used to encode Null/Int/Bool.
++
++ On both 32bit and 64bit, Undefined is encoded as a managed pointer with value 0. This is
++ the same as a nullptr.
+ */
+
+ quint64 _val;
+@@ -137,7 +141,7 @@ public:
+ {
+ quint32 v;
+ memcpy(&v, &b, 4);
+- setTagValue(Managed_Type, v);
++ setTagValue(Managed_Type_Internal, v);
+ }
+ #endif
+
+@@ -153,12 +157,32 @@ public:
+
+ Q_ALWAYS_INLINE void setEmpty()
+ {
+- setTagValue(Empty_Type, value());
++ setTagValue(Empty_Type_Internal, value());
+ }
+
+ Q_ALWAYS_INLINE void setEmpty(int i)
+ {
+- setTagValue(Empty_Type, quint32(i));
++ setTagValue(Empty_Type_Internal, quint32(i));
++ }
++
++ enum Type {
++ Undefined_Type,
++ Managed_Type,
++ Empty_Type,
++ Integer_Type,
++ Boolean_Type,
++ Null_Type,
++ Double_Type
++ };
++
++ inline Type type() const {
++ if (isUndefined()) return Undefined_Type;
++ if (isManaged()) return Managed_Type;
++ if (isEmpty()) return Empty_Type;
++ if (isInteger()) return Integer_Type;
++ if (isBoolean()) return Boolean_Type;
++ if (isNull()) return Null_Type;
++ Q_ASSERT(isDouble()); return Double_Type;
+ }
+
+ #ifndef QV4_USE_64_BIT_VALUE_ENCODING
+@@ -166,101 +190,63 @@ public:
+ SilentNaNBit = 0x00040000,
+ NaN_Mask = 0x7ff80000,
+ NotDouble_Mask = 0x7ffa0000,
+- Type_Mask = 0xffffc000,
+- Immediate_Mask = NotDouble_Mask | 0x00004000 | SilentNaNBit,
+- IsNullOrUndefined_Mask = Immediate_Mask | 0x08000,
++ Immediate_Mask = NotDouble_Mask | 0x00020000u | SilentNaNBit,
+ Tag_Shift = 32
+ };
+- enum ValueType {
+- Undefined_Type = Immediate_Mask | 0x00000,
+- Null_Type = Immediate_Mask | 0x10000,
+- Boolean_Type = Immediate_Mask | 0x08000,
+- Integer_Type = Immediate_Mask | 0x18000,
+- Managed_Type = NotDouble_Mask | 0x00000 | SilentNaNBit,
+- Empty_Type = NotDouble_Mask | 0x18000 | SilentNaNBit
+- };
+-
+- enum ImmediateFlags {
+- ConvertibleToInt = Immediate_Mask | 0x1
+- };
+-
+- enum ValueTypeInternal {
+- Null_Type_Internal = Null_Type | ConvertibleToInt,
+- Boolean_Type_Internal = Boolean_Type | ConvertibleToInt,
+- Integer_Type_Internal = Integer_Type | ConvertibleToInt,
+
++ enum {
++ Managed_Type_Internal = NotDouble_Mask
+ };
+ #else
+- static const quint64 NaNEncodeMask = 0xffff800000000000ll;
+- static const quint64 IsInt32Mask = 0x0002000000000000ll;
+- static const quint64 IsDoubleMask = 0xfffc000000000000ll;
+- static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask;
+- static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll;
+- static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll;
+- static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask;
++ static const quint64 NaNEncodeMask = 0xfffc000000000000ll;
++ static const quint64 Immediate_Mask = 0x00020000u; // bit 48
+
+ 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-16,
++ Tag_Shift = 32,
++ IsDoubleTag_Shift = IsDouble_Shift - Tag_Shift
+ };
+-
+-
++#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 47
++ Null_Type_Internal = ConvertibleToInt | 0x08000u,
++ Boolean_Type_Internal = ConvertibleToInt | 0x04000u,
++ Integer_Type_Internal = ConvertibleToInt | 0x02000u,
++ Managed_Type_Internal = 0
+ };
+-#endif
+
+- inline unsigned type() const {
+- return tag() & Type_Mask;
+- }
++ inline bool isUndefined() const { return tag() == Managed_Type_Internal && value() == 0; }
+
+ // 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 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 (tag() >> (IsManagedOrUndefined_Shift - Tag_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 isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; }
+- inline bool isNumber() const { return tag() == Integer_Type_Internal || (tag() & NotDouble_Mask) != NotDouble_Mask; }
+- inline bool isManaged() const { return tag() == Managed_Type; }
+- inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; }
++ inline bool isManaged() const { return tag() == Managed_Type_Internal && !isUndefined(); }
+ inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; }
+ static inline bool integerCompatible(Value a, Value b) {
+ return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt;
+@@ -500,14 +486,14 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value
+ inline Primitive Primitive::undefinedValue()
+ {
+ Primitive v;
+- v.setTagValue(Undefined_Type, 0);
++ v.setM(nullptr);
+ return v;
+ }
+
+ inline Primitive Primitive::emptyValue()
+ {
+ Primitive v;
+- v.setTagValue(Value::Empty_Type, 0);
++ v.setEmpty(0);
+ return v;
+ }
+
+@@ -553,31 +539,23 @@ inline Primitive Primitive::fromUInt32(uint i)
+
+ struct Encode {
+ static ReturnedValue undefined() {
+- return quint64(Value::Undefined_Type) << Value::Tag_Shift;
++ return Primitive::undefinedValue().rawValue();
+ }
+ static ReturnedValue null() {
+- return quint64(Value::Null_Type_Internal) << Value::Tag_Shift;
++ return Primitive::nullValue().rawValue();
+ }
+
+ Encode(bool b) {
+- val = (quint64(Value::Boolean_Type_Internal) << Value::Tag_Shift) | (uint)b;
++ val = Primitive::fromBoolean(b).rawValue();
+ }
+ Encode(double d) {
+- Value v;
+- v.setDouble(d);
+- val = v.rawValue();
++ val = Primitive::fromDouble(d).rawValue();
+ }
+ Encode(int i) {
+- val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | (uint)i;
++ val = Primitive::fromInt32(i).rawValue();
+ }
+ Encode(uint i) {
+- if (i <= INT_MAX) {
+- val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | i;
+- } else {
+- Value v;
+- v.setDouble(i);
+- val = v.rawValue();
+- }
++ val = Primitive::fromUInt32(i).rawValue();
+ }
+ Encode(ReturnedValue v) {
+ val = v;
+--
+2.9.3
+
diff --git a/PKGBUILD b/PKGBUILD
index a84d502d757e..20f2c814241b 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -156,9 +156,8 @@ build() {
local _srcdir="${srcdir}/${_source_package_name}"
local _bindir="${_srcdir}"
local _basedir="${_srcdir}/qtbase"
- local _waylanddir="${_srcdir}/qtwayland"
+ local _declarativedir="${_srcdir}/qtdeclarative"
local _webenginedir="${_srcdir}/qtwebengine"
- local _locationdir="${_srcdir}/qtlocation"
local _mkspec_dir="${_basedir}/mkspecs/devices/${_mkspec}"
if $_shadow_build; then
@@ -188,6 +187,9 @@ if $_patching; then
#sed -i "s/error/warning/" ${_reducerelocations} || exit 1
#_device_configure_flags="$_device_configure_flags -reduce-relocations"
+ cd ${_declarativedir}
+ patch -p1 < ${startdir}/0001-WIP-V4-Free-up-2-address-bits-in-64bit-mode.patch
+
# Work around our embarresing propensity to stomp on your own tailored build configuration
sed -i "s/O[23]/Os/" ${_basedir}/mkspecs/common/gcc-base.conf || exit 1
fi