aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4value_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4value_p.h')
-rw-r--r--src/qml/jsruntime/qv4value_p.h568
1 files changed, 127 insertions, 441 deletions
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index ce85e48b72..4e901721cb 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -57,8 +57,10 @@
#include "qv4global_p.h"
#include <private/qv4heap_p.h>
#include <private/qv4internalclass_p.h>
+#include <private/qv4staticvalue_p.h>
#include <private/qnumeric_p.h>
+#include <private/qv4calldata_p.h>
QT_BEGIN_NAMESPACE
@@ -68,84 +70,23 @@ namespace Heap {
struct Base;
}
-struct Q_QML_PRIVATE_EXPORT Value
+struct Q_QML_PRIVATE_EXPORT Value : public StaticValue
{
- /*
- 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.)
-
- 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.
-
- 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
-
- 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 00000010 10000000 00000000 00000000 00000000 00000000 00000000 | Null
- 00000000 00000011 00000000 00000000 00000000 00000000 00000000 0000000x | Bool
- 00000000 00000011 10000000 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
- - on 32bit we can use the fact that addresses are 32bits wide, so the tag part (bits 32 to
- 63) are zero. No need to shift.
- */
-
- quint64 _val;
-
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR quint64 &rawValueRef() { return _val; }
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR quint64 rawValue() const { return _val; }
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setRawValue(quint64 raw) { _val = raw; }
-
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- static inline int valueOffset() { return 0; }
- static inline int tagOffset() { return 4; }
-#else // !Q_LITTLE_ENDIAN
- static inline int valueOffset() { return 4; }
- static inline int tagOffset() { return 0; }
-#endif
- static inline constexpr quint64 tagValue(quint32 tag, quint32 value) { return quint64(tag) << 32 | value; }
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
- QML_NEARLY_ALWAYS_INLINE constexpr quint32 value() const { return _val & quint64(~quint32(0)); }
- QML_NEARLY_ALWAYS_INLINE constexpr quint32 tag() const { return _val >> 32; }
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setTag(quint32 tag) { setTagValue(tag, value()); }
+ using HeapBasePtr = Heap::Base *;
+ using ManagedPtr = Managed *;
+
+ Value() = default;
+ constexpr Value(quint64 val) : StaticValue(val) {}
+
+ static constexpr Value fromStaticValue(StaticValue staticValue)
+ {
+ return {staticValue._val};
+ }
#if QT_POINTER_SIZE == 8
- QML_NEARLY_ALWAYS_INLINE Heap::Base *m() const
+ QML_NEARLY_ALWAYS_INLINE HeapBasePtr m() const
{
- Heap::Base *b;
+ HeapBasePtr b;
#ifdef __ia64
// Restore bits 49-47 to bits 63-61, undoing the workaround explained in
// setM below.
@@ -159,7 +100,7 @@ struct Q_QML_PRIVATE_EXPORT Value
#endif
return b;
}
- QML_NEARLY_ALWAYS_INLINE void setM(Heap::Base *b)
+ QML_NEARLY_ALWAYS_INLINE void setM(HeapBasePtr b)
{
memcpy(&_val, &b, 8);
#ifdef __ia64
@@ -171,15 +112,15 @@ struct Q_QML_PRIVATE_EXPORT Value
#endif
}
#elif QT_POINTER_SIZE == 4
- QML_NEARLY_ALWAYS_INLINE Heap::Base *m() const
+ QML_NEARLY_ALWAYS_INLINE HeapBasePtr m() const
{
- Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32));
- Heap::Base *b;
+ Q_STATIC_ASSERT(sizeof(HeapBasePtr) == sizeof(quint32));
+ HeapBasePtr b;
quint32 v = value();
memcpy(&b, &v, 4);
return b;
}
- QML_NEARLY_ALWAYS_INLINE void setM(Heap::Base *b)
+ QML_NEARLY_ALWAYS_INLINE void setM(HeapBasePtr b)
{
quint32 v;
memcpy(&v, &b, 4);
@@ -189,190 +130,11 @@ struct Q_QML_PRIVATE_EXPORT Value
# error "unsupported pointer size"
#endif
- QML_NEARLY_ALWAYS_INLINE constexpr int int_32() const
- {
- return int(value());
- }
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setInt_32(int i)
- {
- setTagValue(quint32(ValueTypeInternal::Integer), quint32(i));
- }
- QML_NEARLY_ALWAYS_INLINE uint uint_32() const { return value(); }
-
- QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setEmpty()
- {
- setTagValue(quint32(ValueTypeInternal::Empty), 0);
- }
-
- // ### Fix for 32 bit (easiest solution is to set highest bit to 1 for mananged/undefined/integercompatible
- // and use negative numbers here
- enum QuickType {
- QT_ManagedOrUndefined = 0,
- QT_ManagedOrUndefined1 = 1,
- QT_ManagedOrUndefined2 = 2,
- QT_ManagedOrUndefined3 = 3,
- QT_Empty = 4,
- QT_Null = 5,
- QT_Bool = 6,
- QT_Int = 7
- // all other values are doubles
- };
-
- enum Type {
- Undefined_Type = 0,
- Managed_Type = 1,
- Empty_Type = 4,
- Null_Type = 5,
- Boolean_Type = 6,
- Integer_Type = 7,
- Double_Type = 8
- };
-
- inline Type type() const {
- int t = quickType();
- if (t < QT_Empty)
- return _val ? Managed_Type : Undefined_Type;
- if (t > QT_Int)
- return Double_Type;
- return static_cast<Type>(t);
- }
-
- // Shared between 32-bit and 64-bit encoding
- enum {
- Tag_Shift = 32
- };
-
- // Used only by 64-bit encoding
- static const quint64 NaNEncodeMask = 0xfffc000000000000ull;
- enum {
- IsDouble_Shift = 64-14,
- IsManagedOrUndefined_Shift = 64-15,
- IsIntegerConvertible_Shift = 64-15,
- IsIntegerOrBool_Shift = 64-16,
- QuickType_Shift = 64 - 17,
- IsPositiveIntShift = 31
- };
-
- static const quint64 Immediate_Mask_64 = 0x00020000u; // bit 49
-
- enum class ValueTypeInternal_64 {
- Empty = Immediate_Mask_64 | 0,
- Null = Immediate_Mask_64 | 0x08000u,
- Boolean = Immediate_Mask_64 | 0x10000u,
- Integer = Immediate_Mask_64 | 0x18000u
- };
-
- // Used only by 32-bit encoding
- enum Masks {
- SilentNaNBit = 0x00040000,
- NotDouble_Mask = 0x7ffa0000,
- };
- static const quint64 Immediate_Mask_32 = NotDouble_Mask | 0x00020000u | SilentNaNBit;
-
- enum class ValueTypeInternal_32 {
- Empty = Immediate_Mask_32 | 0,
- Null = Immediate_Mask_32 | 0x08000u,
- Boolean = Immediate_Mask_32 | 0x10000u,
- Integer = Immediate_Mask_32 | 0x18000u
- };
-
- enum {
- Managed_Type_Internal = 0
- };
-
- using ValueTypeInternal = ValueTypeInternal_64;
-
- enum {
- NaN_Mask = 0x7ff80000,
- };
-
- inline quint64 quickType() const { return (_val >> QuickType_Shift); }
-
- // used internally in property
- inline bool isEmpty() const { return tag() == quint32(ValueTypeInternal::Empty); }
- inline bool isNull() const { return tag() == quint32(ValueTypeInternal::Null); }
- inline bool isBoolean() const { return tag() == quint32(ValueTypeInternal::Boolean); }
- inline bool isInteger() const { return tag() == quint32(ValueTypeInternal::Integer); }
- inline bool isNullOrUndefined() const { return isNull() || isUndefined(); }
- inline bool isNumber() const { return quickType() >= QT_Int; }
-
- inline bool isUndefined() const { return _val == 0; }
- inline bool isDouble() const { return (_val >> IsDouble_Shift); }
- inline bool isManaged() const { return _val && ((_val >> IsManagedOrUndefined_Shift) == 0); }
- inline bool isManagedOrUndefined() const { return ((_val >> IsManagedOrUndefined_Shift) == 0); }
-
- inline bool isIntOrBool() const {
- return (_val >> IsIntegerOrBool_Shift) == 3;
- }
-
- inline bool integerCompatible() const {
- Q_ASSERT(!isEmpty());
- return (_val >> IsIntegerConvertible_Shift) == 1;
- }
- 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() & 0x7ffc0000 ) == 0x00040000; }
-
- inline bool isPositiveInt() const {
-#if QT_POINTER_SIZE == 4
- return isInteger() && int_32() >= 0;
-#else
- return (_val >> IsPositiveIntShift) == (quint64(ValueTypeInternal::Integer) << 1);
-#endif
- }
-
- QML_NEARLY_ALWAYS_INLINE double doubleValue() const {
- Q_ASSERT(isDouble());
- double d;
- Value v = *this;
- v._val ^= NaNEncodeMask;
- memcpy(&d, &v._val, 8);
- return d;
- }
- QML_NEARLY_ALWAYS_INLINE void setDouble(double d) {
- if (qt_is_nan(d))
- d = qt_qnan();
- memcpy(&_val, &d, 8);
- _val ^= NaNEncodeMask;
- Q_ASSERT(isDouble());
- }
inline bool isString() const;
inline bool isStringOrSymbol() const;
inline bool isSymbol() const;
inline bool isObject() const;
inline bool isFunctionObject() const;
- inline bool isInt32() {
- if (tag() == quint32(ValueTypeInternal::Integer))
- return true;
- if (isDouble()) {
- double d = doubleValue();
- if (isInt32(d)) {
- setInt_32(int(d));
- return true;
- }
- }
- return false;
- }
- QML_NEARLY_ALWAYS_INLINE static bool isInt32(double d) {
- int i = int(d);
- return (i == d && !(d == 0 && std::signbit(d)));
- }
- double asDouble() const {
- if (tag() == quint32(ValueTypeInternal::Integer))
- return int_32();
- return doubleValue();
- }
-
- bool booleanValue() const {
- return int_32();
- }
- int integerValue() const {
- return int_32();
- }
QML_NEARLY_ALWAYS_INLINE String *stringValue() const {
if (!isString())
@@ -394,16 +156,16 @@ struct Q_QML_PRIVATE_EXPORT Value
return nullptr;
return reinterpret_cast<Object*>(const_cast<Value *>(this));
}
- QML_NEARLY_ALWAYS_INLINE Managed *managed() const {
+ QML_NEARLY_ALWAYS_INLINE ManagedPtr managed() const {
if (!isManaged())
return nullptr;
return reinterpret_cast<Managed*>(const_cast<Value *>(this));
}
- QML_NEARLY_ALWAYS_INLINE Heap::Base *heapObject() const {
+ QML_NEARLY_ALWAYS_INLINE Value::HeapBasePtr heapObject() const {
return isManagedOrUndefined() ? m() : nullptr;
}
- static inline Value fromHeapObject(Heap::Base *m)
+ static inline Value fromHeapObject(HeapBasePtr m)
{
Value v;
v.setM(m);
@@ -446,12 +208,6 @@ struct Q_QML_PRIVATE_EXPORT Value
static Heap::Object *toObject(ExecutionEngine *e, Value val);
inline bool isPrimitive() const;
- inline bool tryIntegerConversion() {
- bool b = integerCompatible();
- if (b)
- setTagValue(quint32(ValueTypeInternal::Integer), value());
- return b;
- }
template <typename T>
const T *as() const {
@@ -485,13 +241,12 @@ struct Q_QML_PRIVATE_EXPORT Value
return static_cast<const T *>(managed());
}
-#ifndef V4_BOOTSTRAP
uint asArrayLength(bool *ok) const;
-#endif
- ReturnedValue *data_ptr() { return &_val; }
- constexpr ReturnedValue asReturnedValue() const { return _val; }
- static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
+ static constexpr Value fromReturnedValue(ReturnedValue val)
+ {
+ return fromStaticValue(StaticValue::fromReturnedValue(val));
+ }
// As per ES specs
bool sameValue(Value other) const;
@@ -499,21 +254,45 @@ struct Q_QML_PRIVATE_EXPORT Value
inline void mark(MarkStack *markStack);
- inline static constexpr Value emptyValue() { return { tagValue(quint32(ValueTypeInternal::Empty), 0) }; }
- static inline constexpr Value fromBoolean(bool b) { return { tagValue(quint32(ValueTypeInternal::Boolean), b) }; }
- static inline constexpr Value fromInt32(int i) { return { tagValue(quint32(ValueTypeInternal::Integer), quint32(i)) }; }
- inline static constexpr Value undefinedValue() { return { 0 }; }
- static inline constexpr Value nullValue() { return { tagValue(quint32(ValueTypeInternal::Null), 0) }; }
- static inline Value fromDouble(double d);
- static inline Value fromUInt32(uint i);
-
- static double toInteger(double d);
- static int toInt32(double d);
- static unsigned int toUInt32(double d);
+ static double toInteger(double d) { return StaticValue::toInteger(d); }
+ static int toInt32(double d) { return StaticValue::toInt32(d); }
+ static unsigned int toUInt32(double d) { return StaticValue::toUInt32(d); }
+ inline static constexpr Value emptyValue()
+ {
+ return fromStaticValue(StaticValue::emptyValue());
+ }
+ static inline constexpr Value fromBoolean(bool b)
+ {
+ return fromStaticValue(StaticValue::fromBoolean(b));
+ }
+ static inline constexpr Value fromInt32(int i)
+ {
+ return fromStaticValue(StaticValue::fromInt32(i));
+ }
+ inline static constexpr Value undefinedValue()
+ {
+ return fromStaticValue(StaticValue::undefinedValue());
+ }
+ static inline constexpr Value nullValue()
+ {
+ return fromStaticValue(StaticValue::nullValue());
+ }
+ static inline Value fromDouble(double d)
+ {
+ return fromStaticValue(StaticValue::fromDouble(d));
+ }
+ static inline Value fromUInt32(uint i)
+ {
+ return fromStaticValue(StaticValue::fromUInt32(i));
+ }
Value &operator =(const ScopedValue &v);
- Value &operator=(ReturnedValue v) { _val = v; return *this; }
- Value &operator=(Managed *m) {
+ Value &operator=(ReturnedValue v)
+ {
+ StaticValue::operator=(v);
+ return *this;
+ }
+ Value &operator=(ManagedPtr m) {
if (!m) {
setM(nullptr);
} else {
@@ -521,7 +300,7 @@ struct Q_QML_PRIVATE_EXPORT Value
}
return *this;
}
- Value &operator=(Heap::Base *o) {
+ Value &operator=(HeapBasePtr o) {
setM(o);
return *this;
}
@@ -529,43 +308,88 @@ struct Q_QML_PRIVATE_EXPORT Value
template<typename T>
Value &operator=(const Scoped<T> &t);
};
-Q_STATIC_ASSERT(std::is_trivial< Value >::value);
+Q_STATIC_ASSERT(std::is_trivial<Value>::value);
+Q_STATIC_ASSERT(sizeof(Value) == sizeof(StaticValue));
+
+template<>
+inline StaticValue &StaticValue::operator=<Value>(const Value &value)
+{
+ _val = value._val;
+ return *this;
+}
+
+template<typename Managed>
+inline StaticValue &StaticValue::operator=(const Managed &m)
+{
+ *static_cast<Value *>(this) = m;
+ return *this;
+}
+
+template<>
+inline Value &StaticValue::asValue<Value>()
+{
+ return *static_cast<Value *>(this);
+}
+
+template<>
+inline const Value &StaticValue::asValue<Value>() const
+{
+ return *static_cast<const Value *>(this);
+}
+
+template<>
+inline Value *CallData::argValues<Value>()
+{
+ return static_cast<Value *>(static_cast<StaticValue *>(args));
+}
+
+template<>
+inline const Value *CallData::argValues<Value>() const
+{
+ return static_cast<const Value *>(static_cast<const StaticValue *>(args));
+}
+
+template<typename HeapBase>
+inline Encode::Encode(HeapBase *o)
+{
+ val = Value::fromHeapObject(o).asReturnedValue();
+}
inline void Value::mark(MarkStack *markStack)
{
- Heap::Base *o = heapObject();
+ HeapBasePtr o = heapObject();
if (o)
o->mark(markStack);
}
inline bool Value::isString() const
{
- Heap::Base *b = heapObject();
+ HeapBasePtr b = heapObject();
return b && b->internalClass->vtable->isString;
}
bool Value::isStringOrSymbol() const
{
- Heap::Base *b = heapObject();
+ HeapBasePtr b = heapObject();
return b && b->internalClass->vtable->isStringOrSymbol;
}
bool Value::isSymbol() const
{
- Heap::Base *b = heapObject();
+ HeapBasePtr b = heapObject();
return b && b->internalClass->vtable->isStringOrSymbol && !b->internalClass->vtable->isString;
}
inline bool Value::isObject() const
{
- Heap::Base *b = heapObject();
+ HeapBasePtr b = heapObject();
return b && b->internalClass->vtable->isObject;
}
inline bool Value::isFunctionObject() const
{
- Heap::Base *b = heapObject();
+ HeapBasePtr b = heapObject();
return b && b->internalClass->vtable->isFunctionObject;
}
@@ -595,151 +419,12 @@ inline ReturnedValue Value::convertedToNumber() const
inline
ReturnedValue Heap::Base::asReturnedValue() const
{
- return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
-}
-
-inline Value Value::fromDouble(double d)
-{
- Value v;
- v.setDouble(d);
- return v;
-}
-
-inline Value Value::fromUInt32(uint i)
-{
- Value v;
- if (i < INT_MAX) {
- v.setTagValue(quint32(ValueTypeInternal::Integer), i);
- } else {
- v.setDouble(i);
- }
- return v;
-}
-
-struct Double {
- quint64 d;
-
- Double(double dbl) {
- memcpy(&d, &dbl, sizeof(double));
- }
-
- int sign() const {
- return (d >> 63) ? -1 : 1;
- }
-
- bool isDenormal() const {
- return static_cast<int>((d << 1) >> 53) == 0;
- }
-
- int exponent() const {
- return static_cast<int>((d << 1) >> 53) - 1023;
- }
-
- quint64 significant() const {
- quint64 m = (d << 12) >> 12;
- if (!isDenormal())
- m |= (static_cast<quint64>(1) << 52);
- return m;
- }
-
- static int toInt32(double d) {
- int i = static_cast<int>(d);
- if (i == d)
- return i;
- return Double(d).toInt32();
- }
-
- int toInt32() {
- int e = exponent() - 52;
- if (e < 0) {
- if (e <= -53)
- return 0;
- return sign() * static_cast<int>(significant() >> -e);
- } else {
- if (e > 31)
- return 0;
- return sign() * (static_cast<int>(significant()) << e);
- }
- }
-};
-
-inline double Value::toInteger(double d)
-{
- if (std::isnan(d))
- return +0;
- else if (!d || std::isinf(d))
- return d;
- return d >= 0 ? std::floor(d) : std::ceil(d);
-}
-
-inline int Value::toInt32(double value)
-{
- return Double::toInt32(value);
-}
-
-inline unsigned int Value::toUInt32(double d)
-{
- return static_cast<uint>(toInt32(d));
+ return Value::fromHeapObject(const_cast<Value::HeapBasePtr>(this)).asReturnedValue();
}
// For source compat with older code in other modules
using Primitive = Value;
-struct Encode {
- static constexpr ReturnedValue undefined() {
- return Value::undefinedValue().asReturnedValue();
- }
- static constexpr ReturnedValue null() {
- return Value::nullValue().asReturnedValue();
- }
-
- explicit constexpr Encode(bool b)
- : val(Value::fromBoolean(b).asReturnedValue())
- {
- }
- explicit Encode(double d) {
- val = Value::fromDouble(d).asReturnedValue();
- }
- explicit constexpr Encode(int i)
- : val(Value::fromInt32(i).asReturnedValue())
- {
- }
- explicit Encode(uint i) {
- val = Value::fromUInt32(i).asReturnedValue();
- }
- explicit constexpr Encode(ReturnedValue v)
- : val(v)
- {
- }
- constexpr Encode(Value v)
- : val(v.asReturnedValue())
- {
- }
-
- explicit Encode(Heap::Base *o) {
- val = Value::fromHeapObject(o).asReturnedValue();
- }
-
- explicit Encode(Value *o) {
- Q_ASSERT(o);
- val = o->asReturnedValue();
- }
-
- static ReturnedValue smallestNumber(double d) {
- if (Value::isInt32(d))
- return Encode(static_cast<int>(d));
- else
- return Encode(d);
- }
-
- constexpr operator ReturnedValue() const {
- return val;
- }
- quint64 val;
-private:
- explicit Encode(void *);
-};
-
template<typename T>
ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
@@ -796,8 +481,8 @@ inline double Value::toInteger() const
template <size_t o>
struct HeapValue : Value {
static Q_CONSTEXPR size_t offset = o;
- Heap::Base *base() {
- Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ HeapBasePtr base() {
+ HeapBasePtr base = reinterpret_cast<HeapBasePtr>(this) - (offset/sizeof(Heap::Base));
Q_ASSERT(base->inUse());
return base;
}
@@ -805,7 +490,7 @@ struct HeapValue : Value {
void set(EngineBase *e, const Value &newVal) {
WriteBarrier::write(e, base(), data_ptr(), newVal.asReturnedValue());
}
- void set(EngineBase *e, Heap::Base *b) {
+ void set(EngineBase *e, HeapBasePtr b) {
WriteBarrier::write(e, base(), data_ptr(), b->asReturnedValue());
}
};
@@ -817,8 +502,9 @@ struct ValueArray {
uint alloc;
Value values[1];
- Heap::Base *base() {
- Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Value::HeapBasePtr base() {
+ Value::HeapBasePtr base = reinterpret_cast<Value::HeapBasePtr>(this)
+ - (offset/sizeof(Heap::Base));
Q_ASSERT(base->inUse());
return base;
}
@@ -826,7 +512,7 @@ struct ValueArray {
void set(EngineBase *e, uint index, Value v) {
WriteBarrier::write(e, base(), values[index].data_ptr(), v.asReturnedValue());
}
- void set(EngineBase *e, uint index, Heap::Base *b) {
+ void set(EngineBase *e, uint index, Value::HeapBasePtr b) {
WriteBarrier::write(e, base(), values[index].data_ptr(), Value::fromHeapObject(b).asReturnedValue());
}
inline const Value &operator[] (uint index) const {
@@ -855,12 +541,12 @@ struct ValueArray {
const Value *end = v + alloc;
if (alloc > 32*1024) {
// drain from time to time to avoid overflows in the js stack
- Heap::Base **currentBase = markStack->top;
+ Value::HeapBasePtr *currentBase = markStack->top;
while (v < end) {
v->mark(markStack);
++v;
if (markStack->top >= currentBase + 32*1024) {
- Heap::Base **oldBase = markStack->base;
+ Value::HeapBasePtr *oldBase = markStack->base;
markStack->base = currentBase;
markStack->drain();
markStack->base = oldBase;