forked from pool/libqt5-qtdeclarative
372 lines
13 KiB
Diff
372 lines
13 KiB
Diff
|
From aa7c3b35ef9b737c574f436ea35452019a2ff29c Mon Sep 17 00:00:00 2001
|
||
|
From: Erik Verbruggen <erik.verbruggen@digia.com>
|
||
|
Date: Thu, 16 Jun 2016 13:39:57 +0200
|
||
|
Subject: [PATCH 1/1] 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 <simon.hausmann@qt.io>
|
||
|
---
|
||
|
.../qmldbg_debugger/qqmlnativedebugservice.cpp | 2 +-
|
||
|
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 ++++++++++++----------
|
||
|
6 files changed, 63 insertions(+), 73 deletions(-)
|
||
|
|
||
|
Index: qtdeclarative-opensource-src-5.6.1/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
|
||
|
===================================================================
|
||
|
--- qtdeclarative-opensource-src-5.6.1.orig/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
|
||
|
+++ qtdeclarative-opensource-src-5.6.1/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
|
||
|
@@ -549,7 +549,7 @@ void NativeDebugger::handleExpressions(Q
|
||
|
dict[QStringLiteral("name")] = name;
|
||
|
dict[QStringLiteral("valueencoded")] = QStringLiteral("undefined");
|
||
|
output.append(dict);
|
||
|
- } else if (result.ptr && result.ptr->_val) {
|
||
|
+ } else if (result.ptr && result.ptr->rawValue()) {
|
||
|
collector.collect(&output, QString(), name, *result);
|
||
|
} else {
|
||
|
QJsonObject dict;
|
||
|
Index: qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4arraydata.cpp
|
||
|
===================================================================
|
||
|
--- qtdeclarative-opensource-src-5.6.1.orig/src/qml/jsruntime/qv4arraydata.cpp
|
||
|
+++ qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4arraydata.cpp
|
||
|
@@ -93,8 +93,8 @@ Q_STATIC_ASSERT(sizeof(Heap::ArrayData)
|
||
|
|
||
|
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
|
||
|
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
|
||
|
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
|
||
|
// 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;
|
||
|
Index: qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4objectiterator.cpp
|
||
|
===================================================================
|
||
|
--- qtdeclarative-opensource-src-5.6.1.orig/src/qml/jsruntime/qv4objectiterator.cpp
|
||
|
+++ qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4objectiterator.cpp
|
||
|
@@ -68,11 +68,6 @@ void ObjectIterator::init(const Object *
|
||
|
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<ArgumentsObject>()) {
|
||
|
Scope scope(engine);
|
||
|
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
|
||
|
Index: qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4persistent.cpp
|
||
|
===================================================================
|
||
|
--- qtdeclarative-opensource-src-5.6.1.orig/src/qml/jsruntime/qv4persistent.cpp
|
||
|
+++ qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4persistent.cpp
|
||
|
@@ -79,11 +79,9 @@ Page *allocatePage(PersistentValueStorag
|
||
|
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
|
||
|
|
||
|
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);
|
||
|
Index: qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4scopedvalue_p.h
|
||
|
===================================================================
|
||
|
--- qtdeclarative-opensource-src-5.6.1.orig/src/qml/jsruntime/qv4scopedvalue_p.h
|
||
|
+++ qtdeclarative-opensource-src-5.6.1/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<typename T>
|
||
|
inline Value &Value::operator=(const Scoped<T> &t)
|
||
|
{
|
||
|
- _val = t.ptr->val();
|
||
|
+ _val = t.ptr->rawValue();
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
Index: qtdeclarative-opensource-src-5.6.1/src/qml/jsruntime/qv4value_p.h
|
||
|
===================================================================
|
||
|
--- qtdeclarative-opensource-src-5.6.1.orig/src/qml/jsruntime/qv4value_p.h
|
||
|
+++ qtdeclarative-opensource-src-5.6.1/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,52 @@ 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, QT_POINTER_SIZE); return b; }
|
||
|
- Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, QT_POINTER_SIZE); }
|
||
|
+ 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 +296,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 +327,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 +351,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 +401,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<Value *>(m)->_val;
|
||
|
}
|
||
|
@@ -386,9 +409,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 +499,7 @@ struct Q_QML_PRIVATE_EXPORT Primitive :
|
||
|
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 +513,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 +534,7 @@ inline Primitive Primitive::fromDouble(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 +543,7 @@ inline Primitive Primitive::fromUInt32(u
|
||
|
{
|
||
|
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);
|
||
|
}
|