From aa7c3b35ef9b737c574f436ea35452019a2ff29c Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 16 Jun 2016 13:39:57 +0200 Subject: V4: Always set the tag when boxing a pointer in QV4::Value. All setters now store tags, so no-one can play loosy-goosy with the boxed values (and accidentally forget to "tag" a value, resulting in random garbage). Change-Id: Ia0b78aa038d3ff46d5292b14bd593de310da16a0 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arraydata.cpp | 10 ++-- src/qml/jsruntime/qv4objectiterator.cpp | 5 -- src/qml/jsruntime/qv4persistent.cpp | 9 ++-- src/qml/jsruntime/qv4scopedvalue_p.h | 16 +----- src/qml/jsruntime/qv4value_p.h | 94 ++++++++++++++++++--------------- 5 files changed, 62 insertions(+), 72 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index bd736d775e..ec0e6111ab 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -93,8 +93,8 @@ Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData)); static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value) { - Value v = Value::fromReturnedValue(*target); - v.setValue(value); + Value v; + v.setTagValue(Value::fromReturnedValue(*target).tag(), value); *target = v.asReturnedValue(); } @@ -189,7 +189,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt n->value = i; } else { storeValue(lastFree, i); - sparse->arrayData[i].setTag(Value::Empty_Type); + sparse->arrayData[i].setEmpty(); lastFree = &sparse->arrayData[i].rawValueRef(); } } @@ -198,7 +198,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt if (toCopy < sparse->alloc) { for (uint i = toCopy; i < sparse->alloc; ++i) { storeValue(lastFree, i); - sparse->arrayData[i].setTag(Value::Empty_Type); + sparse->arrayData[i].setEmpty(); lastFree = &sparse->arrayData[i].rawValueRef(); } storeValue(lastFree, UINT_MAX); @@ -396,7 +396,7 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) // found two slots in a row uint idx = Value::fromReturnedValue(*last).uint_32(); Value lastV = Value::fromReturnedValue(*last); - lastV.setValue(dd->arrayData[lastV.value() + 1].value()); + lastV.setTagValue(lastV.tag(), dd->arrayData[lastV.value() + 1].value()); *last = lastV.rawValue(); dd->attrs[idx] = Attr_Accessor; return idx; diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index 1413f439b1..d4587df79b 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -68,11 +68,6 @@ void ObjectIterator::init(const Object *o) object->setM(o ? o->m() : 0); current->setM(o ? o->m() : 0); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - object->setTag(QV4::Value::Managed_Type); - current->setTag(QV4::Value::Managed_Type); -#endif - if (object->as()) { Scope scope(engine); Scoped (scope, object->asReturnedValue())->fullyCreate(); diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 1b0d6383e0..fd3bd1f660 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -79,11 +79,9 @@ Page *allocatePage(PersistentValueStorage *storage) if (p->header.next) p->header.next->header.prev = &p->header.next; for (int i = 0; i < kEntriesPerPage - 1; ++i) { - p->values[i].setTag(QV4::Value::Empty_Type); - p->values[i].setInt_32(i + 1); + p->values[i].setEmpty(i + 1); } - p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type); - p->values[kEntriesPerPage - 1].setInt_32(-1); + p->values[kEntriesPerPage - 1].setEmpty(-1); storage->firstPage = p; @@ -205,8 +203,7 @@ void PersistentValueStorage::free(Value *v) Page *p = getPage(v); - v->setTag(QV4::Value::Empty_Type); - v->setInt_32(p->header.freeList); + v->setEmpty(p->header.freeList); p->header.freeList = v - p->values; if (!--p->header.refCount) freePage(p); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index ca7efb1e79..0b063ee4b8 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -120,9 +120,6 @@ struct ScopedValue { ptr = scope.engine->jsStackTop++; ptr->setM(o); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - ptr->setTag(QV4::Value::Managed_Type); -#endif } ScopedValue(const Scope &scope, Managed *m) @@ -144,9 +141,6 @@ struct ScopedValue ScopedValue &operator=(Heap::Base *o) { ptr->setM(o); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - ptr->setTag(QV4::Value::Managed_Type); -#endif return *this; } @@ -186,18 +180,12 @@ struct Scoped inline void setPointer(const Managed *p) { ptr->setM(p ? p->m() : 0); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - ptr->setTag(QV4::Value::Managed_Type); -#endif } Scoped(const Scope &scope) { ptr = scope.engine->jsStackTop++; ptr->setM(0); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - ptr->setTag(QV4::Value::Managed_Type); -#endif } Scoped(const Scope &scope, const Value &v) @@ -339,14 +327,14 @@ struct ScopedCallData { inline Value &Value::operator =(const ScopedValue &v) { - _val = v.ptr->val(); + _val = v.ptr->rawValue(); return *this; } template inline Value &Value::operator=(const Scoped &t) { - _val = t.ptr->val(); + _val = t.ptr->rawValue(); return *this; } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 6bd39355c5..7c2bb31a00 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -66,6 +66,7 @@ typedef uint Bool; struct Q_QML_PRIVATE_EXPORT Value { +private: /* We use two different ways of encoding JS values. One for 32bit and one for 64bit systems. @@ -90,10 +91,10 @@ struct Q_QML_PRIVATE_EXPORT Value quint64 _val; - Q_ALWAYS_INLINE quint64 val() const { return _val; } - Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; } - Q_ALWAYS_INLINE void setValue(quint32 v) { memcpy(&_val, &v, 4); } - Q_ALWAYS_INLINE void setTag(quint32 t) { memcpy(4 + (quint8 *)&_val, &t, 4); } +public: + Q_ALWAYS_INLINE quint64 &rawValueRef() { return _val; } + Q_ALWAYS_INLINE quint64 rawValue() const { return _val; } + Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; } #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static inline int valueOffset() { return 0; } @@ -113,17 +114,53 @@ struct Q_QML_PRIVATE_EXPORT Value Q_ALWAYS_INLINE Heap::Base *m() const { Q_UNREACHABLE(); return Q_NULLPTR; } Q_ALWAYS_INLINE void setM(Heap::Base *b) { Q_UNUSED(b); Q_UNREACHABLE(); } #elif defined(QV4_USE_64_BIT_VALUE_ENCODING) - Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; } - Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); } + Q_ALWAYS_INLINE Heap::Base *m() const + { + Heap::Base *b; + memcpy(&b, &_val, 8); + return b; + } + Q_ALWAYS_INLINE void setM(Heap::Base *b) + { + memcpy(&_val, &b, 8); + } #else // !QV4_USE_64_BIT_VALUE_ENCODING - Q_ALWAYS_INLINE Heap::Base *m() const { Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32)); Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; } - Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); } + Q_ALWAYS_INLINE Heap::Base *m() const + { + Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32)); + Heap::Base *b; + quint32 v = value(); + memcpy(&b, &v, 4); + return b; + } + Q_ALWAYS_INLINE void setM(Heap::Base *b) + { + quint32 v; + memcpy(&v, &b, 4); + setTagValue(Managed_Type, v); + } #endif - Q_ALWAYS_INLINE int int_32() const { int i; quint32 v = value(); memcpy(&i, &v, 4); return i; } - Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); } + Q_ALWAYS_INLINE int int_32() const + { + return int(value()); + } + Q_ALWAYS_INLINE void setInt_32(int i) + { + setTagValue(Integer_Type_Internal, quint32(i)); + } Q_ALWAYS_INLINE uint uint_32() const { return value(); } + Q_ALWAYS_INLINE void setEmpty() + { + setTagValue(Empty_Type, value()); + } + + Q_ALWAYS_INLINE void setEmpty(int i) + { + setTagValue(Empty_Type, quint32(i)); + } + #ifndef QV4_USE_64_BIT_VALUE_ENCODING enum Masks { SilentNaNBit = 0x00040000, @@ -260,7 +297,6 @@ struct Q_QML_PRIVATE_EXPORT Value int i = (int)d; if (i == d) { setInt_32(i); - setTag(Integer_Type_Internal); return true; } } @@ -292,22 +328,10 @@ struct Q_QML_PRIVATE_EXPORT Value return m(); } - Q_ALWAYS_INLINE quint64 &rawValueRef() { - return _val; - } - Q_ALWAYS_INLINE quint64 rawValue() const { - return _val; - } - Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; } - static inline Value fromHeapObject(Heap::Base *m) { Value v; - v.setRawValue(0); v.setM(m); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - v.setTag(Managed_Type); -#endif return v; } @@ -328,7 +352,7 @@ struct Q_QML_PRIVATE_EXPORT Value inline bool tryIntegerConversion() { bool b = integerCompatible(); if (b) - setTag(Integer_Type_Internal); + setTagValue(Integer_Type_Internal, value()); return b; } @@ -378,7 +402,7 @@ struct Q_QML_PRIVATE_EXPORT Value Value &operator=(ReturnedValue v) { _val = v; return *this; } Value &operator=(Managed *m) { if (!m) { - setTagValue(Undefined_Type, 0); + setM(0); } else { _val = reinterpret_cast(m)->_val; } @@ -386,9 +410,6 @@ struct Q_QML_PRIVATE_EXPORT Value } Value &operator=(Heap::Base *o) { setM(o); -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - setTag(Managed_Type); -#endif return *this; } @@ -479,13 +500,7 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value inline Primitive Primitive::undefinedValue() { Primitive v; -#ifdef QV4_USE_64_BIT_VALUE_ENCODING - v.setRawValue(quint64(Undefined_Type) << Tag_Shift); -#else - v.setRawValue(0); - v.setTag(Undefined_Type); - v.setValue(0); -#endif + v.setTagValue(Undefined_Type, 0); return v; } @@ -499,11 +514,7 @@ inline Primitive Primitive::emptyValue() inline Primitive Primitive::nullValue() { Primitive v; -#ifndef QV4_USE_64_BIT_VALUE_ENCODING - v.setRawValue(quint64(Null_Type_Internal) << Tag_Shift); -#else v.setTagValue(Null_Type_Internal, 0); -#endif return v; } @@ -524,7 +535,7 @@ inline Primitive Primitive::fromDouble(double d) inline Primitive Primitive::fromInt32(int i) { Primitive v; - v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors. + v.setTagValue(Integer_Type_Internal, 0); v.setInt_32(i); return v; } @@ -533,8 +544,7 @@ inline Primitive Primitive::fromUInt32(uint i) { Primitive v; if (i < INT_MAX) { - v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors. - v.setInt_32((int)i); + v.setTagValue(Integer_Type_Internal, i); } else { v.setDouble(i); } -- cgit v1.2.3