diff options
author | Donald Carr | 2016-09-06 13:30:39 -0700 |
---|---|---|
committer | Donald Carr | 2016-09-06 13:42:04 -0700 |
commit | 435654e04fd47e83a723e7b9aed891794615544d (patch) | |
tree | ed363ba9932ff98e872ba445a0a3573ab0b15e7c | |
parent | fca7d208bd6f552765f4d011d8295b1a51bb0a60 (diff) | |
download | aur-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.patch | 543 | ||||
-rw-r--r-- | PKGBUILD | 6 |
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 + @@ -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 |