aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-10-18 08:33:26 +0200
committerLiang Qi <liang.qi@qt.io>2016-10-18 08:33:26 +0200
commitf04c2c40fd7ee91e5cbff2ca4df0fdc30dfbbcd5 (patch)
tree4e96d097987deb8d4d1a963e911dcbd1641a8502 /src/qml
parent0da811cdfebdae1d96c99fe681e6a776e73d2f7f (diff)
parente76ed6a2655894bd671ee7397a15f2e57cfc8d33 (diff)
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts: src/qml/jsruntime/qv4variantobject.cpp src/qml/types/qquickworkerscript.cpp src/quick/scenegraph/util/qsgdefaultpainternode_p.h tools/qmljs/qmljs.cpp Change-Id: I876242714ec8c046238d8fd673a5ace2455b2b59
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/compiler.pri14
-rw-r--r--src/qml/compiler/qv4compileddata_p.h14
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h5
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h2
-rw-r--r--src/qml/configure.json37
-rw-r--r--src/qml/debugger/qqmldebug.cpp18
-rw-r--r--src/qml/debugger/qqmlmemoryprofiler.cpp37
-rw-r--r--src/qml/debugger/qqmlmemoryprofiler_p.h48
-rw-r--r--src/qml/doc/src/cppclasses/topic.qdoc4
-rw-r--r--src/qml/doc/src/cppintegration/exposecppattributes.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc8
-rw-r--r--src/qml/doc/src/qmllanguageref/documents/scope.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc5
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/signals.qdoc3
-rw-r--r--src/qml/jit/qv4assembler.cpp38
-rw-r--r--src/qml/jit/qv4assembler_p.h5
-rw-r--r--src/qml/jit/qv4isel_masm.cpp104
-rw-r--r--src/qml/jit/qv4isel_masm_p.h4
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp10
-rw-r--r--src/qml/jsruntime/jsruntime.pri9
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h22
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp15
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h8
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp33
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h14
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp17
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4context_p.h10
-rw-r--r--src/qml/jsruntime/qv4context_p_p.h2
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp4
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h4
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4engine.cpp20
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp97
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h44
-rw-r--r--src/qml/jsruntime/qv4function.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp66
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h40
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4include.cpp14
-rw-r--r--src/qml/jsruntime/qv4include_p.h4
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp12
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4managed_p.h23
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h2
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp6
-rw-r--r--src/qml/jsruntime/qv4object_p.h56
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp24
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h51
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp4
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h2
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp58
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h45
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp28
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h22
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp12
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h2
-rw-r--r--src/qml/jsruntime/qv4script.cpp7
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp99
-rw-r--r--src/qml/jsruntime/qv4string.cpp8
-rw-r--r--src/qml/jsruntime/qv4string_p.h8
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h6
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp13
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h13
-rw-r--r--src/qml/jsruntime/qv4value_p.h267
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp35
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h22
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp26
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h3
-rw-r--r--src/qml/memory/qv4heap_p.h50
-rw-r--r--src/qml/memory/qv4mm.cpp17
-rw-r--r--src/qml/memory/qv4mm_p.h44
-rw-r--r--src/qml/qml.pro10
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp23
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp21
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h8
-rw-r--r--src/qml/qml/qqmlengine.cpp8
-rw-r--r--src/qml/qml/qqmlengine.h4
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlfile.cpp20
-rw-r--r--src/qml/qml/qqmlfile.h2
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp24
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h13
-rw-r--r--src/qml/qml/qqmllocale.cpp44
-rw-r--r--src/qml/qml/qqmllocale_p.h10
-rw-r--r--src/qml/qml/qqmlloggingcategory.cpp2
-rw-r--r--src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp4
-rw-r--r--src/qml/qml/qqmlnetworkaccessmanagerfactory.h4
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp7
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h14
-rw-r--r--src/qml/qml/qqmltypeloader.cpp65
-rw-r--r--src/qml/qml/qqmltypeloader_p.h13
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp8
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp53
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h18
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp42
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp82
-rw-r--r--src/qml/qml/qqmlxmlhttprequest_p.h4
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp21
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h16
-rw-r--r--src/qml/qml/v8/qv8engine.cpp6
-rw-r--r--src/qml/qml/v8/qv8engine_p.h2
-rw-r--r--src/qml/qtqmlglobal.h4
-rw-r--r--src/qml/qtqmlglobal_p.h4
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp37
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h9
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h13
-rw-r--r--src/qml/types/qquickworkerscript.cpp12
-rw-r--r--src/qml/util/qqmlchangeset_p.h25
125 files changed, 1533 insertions, 984 deletions
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index e49f5c40a5..a63de67b4c 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -25,8 +25,6 @@ SOURCES += \
HEADERS += \
$$PWD/qqmltypecompiler_p.h \
- $$PWD/qv4isel_moth_p.h \
- $$PWD/qv4instr_moth_p.h \
$$PWD/qqmlpropertycachecreator_p.h \
$$PWD/qqmlpropertyvalidator_p.h \
$$PWD/qv4compilationunitmapper_p.h
@@ -34,8 +32,6 @@ HEADERS += \
SOURCES += \
$$PWD/qqmltypecompiler.cpp \
- $$PWD/qv4instr_moth.cpp \
- $$PWD/qv4isel_moth.cpp \
$$PWD/qqmlpropertycachecreator.cpp \
$$PWD/qqmlpropertyvalidator.cpp \
$$PWD/qv4compilationunitmapper.cpp
@@ -43,4 +39,14 @@ SOURCES += \
unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp
else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp
+qtConfig(qml-interpreter) {
+ HEADERS += \
+ $$PWD/qv4instr_moth_p.h \
+ $$PWD/qv4isel_moth_p.h
+ SOURCES += \
+ $$PWD/qv4instr_moth.cpp \
+ $$PWD/qv4isel_moth.cpp
+}
+
+
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index ae8677138e..fe18024070 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -71,7 +71,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x04
+#define QV4_DATA_STRUCTURE_VERSION 0x05
class QIODevice;
class QQmlPropertyCache;
@@ -202,6 +202,8 @@ struct String
}
};
+// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
+// for unaligned access. The ordering of the fields is also from largest to smallest.
struct Function
{
enum Flags : unsigned int {
@@ -212,6 +214,11 @@ struct Function
HasCatchOrWith = 0x10
};
+ // Absolute offset into file where the code for this function is located. Only used when the function
+ // is serialized.
+ LEUInt64 codeOffset;
+ LEUInt64 codeSize;
+
LEUInt32 nameIndex;
LEUInt32 nFormals;
LEUInt32 formalsOffset;
@@ -229,11 +236,6 @@ struct Function
LEUInt32 dependingScopePropertiesOffset; // Array of int pairs (property index and notify index)
// Qml Extensions End
- // Absolute offset into file where the code for this function is located. Only used when the function
- // is serialized.
- LEUInt64 codeOffset;
- LEUInt64 codeSize;
-
// quint32 formalsIndex[nFormals]
// quint32 localsIndex[nLocals]
// quint32 offsetForInnerFunctions[nInnerFunctions]
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index beb43376ee..b83bcdb83b 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -50,12 +50,13 @@
//
// We mean it.
//
-
-#include <QtCore/qglobal.h>
+#include <private/qv4global_p.h>
#include <private/qv4value_p.h>
#include <private/qv4function_p.h>
#include <private/qv4runtime_p.h>
+QT_REQUIRE_CONFIG(qml_interpreter);
+
QT_BEGIN_NAMESPACE
#ifdef QT_NO_QML_DEBUGGER
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 9699555670..afe5fe342e 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -59,6 +59,8 @@
#include <private/qv4value_p.h>
#include "qv4instr_moth_p.h"
+QT_REQUIRE_CONFIG(qml_interpreter);
+
QT_BEGIN_NAMESPACE
namespace QV4 {
diff --git a/src/qml/configure.json b/src/qml/configure.json
new file mode 100644
index 0000000000..d22ba3b8f0
--- /dev/null
+++ b/src/qml/configure.json
@@ -0,0 +1,37 @@
+{
+ "module": "qml",
+ "depends": [
+ "core-private",
+ "network-private"
+ ],
+
+ "commandline": {
+ "options": {
+ "qml-interpreter": "boolean",
+ "qml-network": "boolean"
+ }
+ },
+
+ "features": {
+ "qml-interpreter": {
+ "label": "QML interpreter",
+ "purpose": "Support for the QML interpreter",
+ "output": [ "privateFeature" ]
+ },
+ "qml-network": {
+ "label": "QML network support",
+ "purpose": "Provides network transparency for QML",
+ "output": [ "publicFeature" ]
+ }
+ },
+
+ "summary": [
+ {
+ "section": "Qt QML",
+ "entries": [
+ "qml-interpreter",
+ "qml-network"
+ ]
+ }
+ ]
+}
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 386fb60b3a..b2c4b139ee 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -169,4 +169,22 @@ bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName,
return connector ? connector->open(configuration) : false;
}
+enum { HookCount = 3 };
+
+// Only add to the end, and bump version if you do.
+quintptr Q_QML_EXPORT qtDeclarativeHookData[] = {
+ // Version of this Array. Bump if you add to end.
+ 1,
+
+ // Number of entries in this array.
+ HookCount,
+
+ // TypeInformationVersion, an integral value, bumped whenever private
+ // object sizes or member offsets that are used in Qt Creator's
+ // data structure "pretty printing" change.
+ 2
+};
+
+Q_STATIC_ASSERT(HookCount == sizeof(qtDeclarativeHookData) / sizeof(qtDeclarativeHookData[0]));
+
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlmemoryprofiler.cpp b/src/qml/debugger/qqmlmemoryprofiler.cpp
index 60f6d96eaf..53d4e7ab21 100644
--- a/src/qml/debugger/qqmlmemoryprofiler.cpp
+++ b/src/qml/debugger/qqmlmemoryprofiler.cpp
@@ -38,18 +38,11 @@
****************************************************************************/
#include "qqmlmemoryprofiler_p.h"
-#include <QUrl>
QT_BEGIN_NAMESPACE
-enum LibraryState
-{
- Unloaded,
- Failed,
- Loaded
-};
-static LibraryState state = Unloaded;
+QQmlMemoryScope::LibraryState QQmlMemoryScope::state = QQmlMemoryScope::Unloaded;
typedef void (qmlmemprofile_stats)(int *allocCount, int *bytesAllocated);
typedef void (qmlmemprofile_clear)();
@@ -73,7 +66,7 @@ static qmlmemprofile_is_enabled *memprofile_is_enabled;
extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol);
#endif
-static bool openLibrary()
+bool QQmlMemoryScope::doOpenLibrary()
{
#if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY)
if (state == Unloaded) {
@@ -97,28 +90,22 @@ static bool openLibrary()
return state == Loaded;
}
-QQmlMemoryScope::QQmlMemoryScope(const QUrl &url)
- : QQmlMemoryScope(url.path().toUtf8().constData())
-{
-}
-
-QQmlMemoryScope::QQmlMemoryScope(const char *string) : pushed(false)
+void QQmlMemoryScope::init(const char *string)
{
- if (openLibrary() && memprofile_is_enabled()) {
+ if (memprofile_is_enabled()) {
memprofile_push_location(string, 0);
pushed = true;
}
}
-QQmlMemoryScope::~QQmlMemoryScope()
+void QQmlMemoryScope::done()
{
- if (pushed)
- memprofile_pop_location();
+ memprofile_pop_location();
}
bool QQmlMemoryProfiler::isEnabled()
{
- if (openLibrary())
+ if (QQmlMemoryScope::openLibrary())
return memprofile_is_enabled();
return false;
@@ -126,31 +113,31 @@ bool QQmlMemoryProfiler::isEnabled()
void QQmlMemoryProfiler::enable()
{
- if (openLibrary())
+ if (QQmlMemoryScope::openLibrary())
memprofile_enable();
}
void QQmlMemoryProfiler::disable()
{
- if (openLibrary())
+ if (QQmlMemoryScope::openLibrary())
memprofile_disable();
}
void QQmlMemoryProfiler::clear()
{
- if (openLibrary())
+ if (QQmlMemoryScope::openLibrary())
memprofile_clear();
}
void QQmlMemoryProfiler::stats(int *allocCount, int *bytesAllocated)
{
- if (openLibrary())
+ if (QQmlMemoryScope::openLibrary())
memprofile_stats(allocCount, bytesAllocated);
}
void QQmlMemoryProfiler::save(const char *filename)
{
- if (openLibrary())
+ if (QQmlMemoryScope::openLibrary())
memprofile_save(filename);
}
diff --git a/src/qml/debugger/qqmlmemoryprofiler_p.h b/src/qml/debugger/qqmlmemoryprofiler_p.h
index 59f08704ca..fb71c999c3 100644
--- a/src/qml/debugger/qqmlmemoryprofiler_p.h
+++ b/src/qml/debugger/qqmlmemoryprofiler_p.h
@@ -52,6 +52,7 @@
//
#include <private/qtqmlglobal_p.h>
+#include <QUrl>
QT_BEGIN_NAMESPACE
@@ -62,16 +63,53 @@ QT_BEGIN_NAMESPACE
#else
-class QUrl;
-
class Q_QML_PRIVATE_EXPORT QQmlMemoryScope
{
public:
- explicit QQmlMemoryScope(const QUrl &url);
- explicit QQmlMemoryScope(const char *string);
- ~QQmlMemoryScope();
+ explicit QQmlMemoryScope(const QUrl &url)
+ : pushed(false)
+ {
+ if (Q_UNLIKELY(openLibrary()))
+ init(url.path().toUtf8().constData());
+ }
+
+ explicit QQmlMemoryScope(const char *string)
+ : pushed(false)
+ {
+ if (Q_UNLIKELY(openLibrary()))
+ init(string);
+ }
+
+ ~QQmlMemoryScope()
+ {
+ if (Q_UNLIKELY(pushed))
+ done();
+ }
+
+ enum LibraryState
+ {
+ Unloaded,
+ Failed,
+ Loaded
+ };
+
+ static bool openLibrary()
+ {
+ if (Q_LIKELY(state == Loaded))
+ return true;
+ if (state == Failed)
+ return false;
+
+ return doOpenLibrary();
+ }
private:
+ Q_NEVER_INLINE void init(const char *string);
+ Q_NEVER_INLINE void done();
+ Q_NEVER_INLINE static bool doOpenLibrary();
+
+ static LibraryState state;
+
bool pushed;
};
diff --git a/src/qml/doc/src/cppclasses/topic.qdoc b/src/qml/doc/src/cppclasses/topic.qdoc
index ddb29fbb14..133f9bc72c 100644
--- a/src/qml/doc/src/cppclasses/topic.qdoc
+++ b/src/qml/doc/src/cppclasses/topic.qdoc
@@ -91,7 +91,7 @@ at run-time using a QQmlComponent. An instance of the QQmlComponent class can
be created in C++ directly, or via the \l{QtQml::Qt::createComponent()}
{Qt.createComponent()} function in imperative QML code. Arbitrary expressions
can be calculated in C++ via the QQmlExpression class, and such expressions
-can interact directly the QML context.
+can interact directly with the QML context.
\section2 The QQmlComponent Class
@@ -106,7 +106,7 @@ how to use QQmlComponent.
The QQmlExpression class provides a way for clients to evaluate JavaScript
expressions from C++, using a particular QML evaluation context. This allows
-clients to access QML objects by id, for example. The result of evaluation
+clients to access QML objects by id, for example. The result of the evaluation
is returned as a QVariant, and the conversion rules are defined by the QML
engine.
diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
index f5aea0b01a..ed0d049564 100644
--- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
+++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
@@ -71,7 +71,7 @@ type that is supported by the QML engine.
By default, the engine supports a number of Qt C++ types and can automatically
convert them as appropriately when used from QML. Additionally, C++ classes
that are \l{Registering C++ types with the QML type system}{registered} with
-the QML type system can be can be used as data types, as can their enums if
+the QML type system can be used as data types, as can their enums if
appropriately registered. See \l{qtqml-cppintegration-data.html}{Data Type
Conversion Between QML and C++} for further information.
diff --git a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc
index 4b4b25796c..03a7ddfb19 100644
--- a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc
@@ -43,7 +43,8 @@ For example, below is a document that declares a \l Rectangle with a child \l Mo
import QtQuick 2.0
Rectangle {
- width: 100; height: 100
+ property int side: 100
+ width: side; height: side
color: "red"
MouseArea {
@@ -87,7 +88,7 @@ For example, the root object type in the \c SquareButton.qml file above is \l Re
import QtQuick 2.0
Column {
- SquareButton { width: 50; height: 50 }
+ SquareButton { side: 50 }
SquareButton { x: 50; color: "blue" }
SquareButton { radius: 10 }
}
@@ -112,7 +113,8 @@ Rectangle {
root.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
- width: 100; height: 100
+ property int side: 100
+ width: side; height: side
color: "red"
MouseArea {
diff --git a/src/qml/doc/src/qmllanguageref/documents/scope.qdoc b/src/qml/doc/src/qmllanguageref/documents/scope.qdoc
index 3e3bbaca98..eaf1747a6d 100644
--- a/src/qml/doc/src/qmllanguageref/documents/scope.qdoc
+++ b/src/qml/doc/src/qmllanguageref/documents/scope.qdoc
@@ -105,7 +105,7 @@ ListView {
\section1 Binding Scope Object
-An object which has a \l{Property Binding}{property binding} is known has the
+An object which has a \l{Property Binding}{property binding} is known as the
binding's \e{scope object}. In the following example, the \l Item object is
the binding's scope object.
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index 3692605c18..030eb72b5f 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -191,7 +191,7 @@ which was then imported by the client), then a property of type
\section3 Assigning Values to Property Attributes
-The value of a property of an object instance may specified in two separate ways:
+The value of a property of an object instance may be specified in two separate ways:
\list
\li a value assignment on initialization
\li an imperative value assignment
@@ -724,7 +724,8 @@ Rectangle {
signal activated(real xPosition, real yPosition)
signal deactivated
- width: 100; height: 100
+ property int side: 100
+ width: side; height: side
MouseArea {
anchors.fill: parent
diff --git a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
index 602b202ed4..4a022f2b0b 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/signals.qdoc
@@ -187,7 +187,8 @@ Rectangle {
signal activated(real xPosition, real yPosition)
- width: 100; height: 100
+ property int side: 100
+ width: side; height: side
MouseArea {
anchors.fill: parent
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 5e05f14192..e1acc33f82 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -196,8 +196,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) {
@@ -210,8 +232,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) {
@@ -408,9 +433,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 7d4d90882a..94478cd9cd 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -319,6 +319,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 12b1eb4473..515b8aea4d 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -686,7 +686,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
}
@@ -948,7 +948,7 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
tag = QV4::Value::Integer_Type_Internal;
break;
default:
- tag = QV4::Value::Undefined_Type;
+ tag = 31337; // bogus value
Q_UNREACHABLE();
}
_as->store32(Assembler::TrustedImm32(tag), addr);
@@ -1092,7 +1092,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
@@ -1183,10 +1183,15 @@ 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::IsIntegerConvertible_Shift), Assembler::ScratchRegister);
+ Assembler::Jump isIntConvertible = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(3));
+
+ // nope, not integer convertible, so check for a double:
+ _as->urshift64(Assembler::TrustedImm32(
+ QV4::Value::IsDoubleTag_Shift - QV4::Value::IsIntegerConvertible_Shift),
+ Assembler::ScratchRegister);
+ Assembler::Jump fallback = _as->branch32(Assembler::GreaterThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
// it's a double
_as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
@@ -1201,7 +1206,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe
generateRuntimeCall(Assembler::ReturnValueRegister, 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) {
@@ -1396,7 +1401,7 @@ void InstructionSelection::visitCJump(IR::CJump *s)
Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
Address tag = temp;
tag.offset += QV4::Value::tagOffset();
- Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
+ Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal));
Address data = temp;
data.offset += QV4::Value::valueOffset();
@@ -1563,7 +1568,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
tag = QV4::Value::Boolean_Type_Internal;
break;
default:
- tag = QV4::Value::Undefined_Type;
+ tag = 31337; // bogus value
Q_UNREACHABLE();
}
_as->or64(Assembler::TrustedImm64(tag << 32),
@@ -1744,9 +1749,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;
@@ -1762,16 +1767,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;
@@ -1782,7 +1785,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);
@@ -1795,9 +1798,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;
}
@@ -1888,10 +1936,14 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
if (binop->op == IR::OpNotEqual)
qSwap(trueBlock, falseBlock);
Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Null_Type_Internal)));
- Assembler::Jump isUndefined = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Undefined_Type)));
+ Assembler::Jump isNotUndefinedTag = _as->branch32(Assembler::NotEqual, tagReg, Assembler::TrustedImm32(int(QV4::Value::Managed_Type_Internal)));
+ tagAddr.offset -= 4;
+ _as->load32(tagAddr, tagReg);
+ Assembler::Jump isNotUndefinedValue = _as->branch32(Assembler::NotEqual, tagReg, Assembler::TrustedImm32(0));
_as->addPatch(trueBlock, isNull);
- _as->addPatch(trueBlock, isUndefined);
- _as->jumpToBlock(_block, falseBlock);
+ _as->addPatch(falseBlock, isNotUndefinedTag);
+ _as->addPatch(falseBlock, isNotUndefinedValue);
+ _as->jumpToBlock(_block, trueBlock);
return true;
}
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 1742ff9a36..5c693e0736 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -172,8 +172,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/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 86c7554924..ce472ce7e5 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -103,11 +103,11 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
return;
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- it->d()->it.flags = QV4::ObjectIterator::NoFlags;
+ it->d()->it().flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
QV4::Property nextProperty;
QV4::PropertyAttributes nextAttributes;
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
d_ptr->nextName.set(v4, nm.asReturnedValue());
}
@@ -157,7 +157,7 @@ bool QJSValueIterator::next()
QV4::ScopedString nm(scope);
QV4::Property nextProperty;
QV4::PropertyAttributes nextAttributes;
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
d_ptr->nextName.set(v4, nm.asReturnedValue());
return d_ptr->currentName.as<QV4::String>() || d_ptr->currentIndex != UINT_MAX;
}
@@ -231,11 +231,11 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&object));
d_ptr->iterator.set(v4, v4->newForEachIteratorObject(o));
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- it->d()->it.flags = QV4::ObjectIterator::NoFlags;
+ it->d()->it().flags = QV4::ObjectIterator::NoFlags;
QV4::ScopedString nm(scope);
QV4::Property nextProperty;
QV4::PropertyAttributes nextAttributes;
- it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
+ it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes);
d_ptr->nextName.set(v4, nm.asReturnedValue());
return *this;
}
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 63cf8779d2..4343924436 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -38,7 +38,6 @@ SOURCES += \
$$PWD/qv4sequenceobject.cpp \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
- $$PWD/qv4vme_moth.cpp \
$$PWD/qv4arraybuffer.cpp \
$$PWD/qv4typedarray.cpp \
$$PWD/qv4dataview.cpp
@@ -87,12 +86,18 @@ HEADERS += \
$$PWD/qv4sequenceobject_p.h \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
- $$PWD/qv4vme_moth_p.h \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
$$PWD/qv4typedarray_p.h \
$$PWD/qv4dataview_p.h
+qtConfig(qml-interpreter) {
+ HEADERS += \
+ $$PWD/qv4vme_moth_p.h
+ SOURCES += \
+ $$PWD/qv4vme_moth.cpp
+}
+
}
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 156c21ca66..0dfdf25158 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -45,9 +45,10 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
-Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
- : fullyCreated(false)
+void Heap::ArgumentsObject::init(QV4::CallContext *context)
{
+ Object::init();
+ fullyCreated = false;
this->context = context->d();
Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 6ccfd89fd4..37a8d0a94a 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -60,12 +60,12 @@ namespace QV4 {
namespace Heap {
struct ArgumentsGetterFunction : FunctionObject {
- inline ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index);
+ inline void init(QV4::ExecutionContext *scope, uint index);
uint index;
};
struct ArgumentsSetterFunction : FunctionObject {
- inline ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index);
+ inline void init(QV4::ExecutionContext *scope, uint index);
uint index;
};
@@ -75,7 +75,7 @@ struct ArgumentsObject : Object {
CalleePropertyIndex = 1,
CallerPropertyIndex = 3
};
- ArgumentsObject(QV4::CallContext *context);
+ void init(QV4::CallContext *context);
Pointer<CallContext> context;
bool fullyCreated;
Pointer<MemberData> mappedArguments;
@@ -91,11 +91,11 @@ struct ArgumentsGetterFunction: FunctionObject
static void call(const Managed *that, Scope &scope, CallData *d);
};
-inline
-Heap::ArgumentsGetterFunction::ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index)
- : Heap::FunctionObject(scope)
- , index(index)
+inline void
+Heap::ArgumentsGetterFunction::init(QV4::ExecutionContext *scope, uint index)
{
+ Heap::FunctionObject::init(scope);
+ this->index = index;
}
struct ArgumentsSetterFunction: FunctionObject
@@ -106,11 +106,11 @@ struct ArgumentsSetterFunction: FunctionObject
static void call(const Managed *that, Scope &scope, CallData *callData);
};
-inline
-Heap::ArgumentsSetterFunction::ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index)
- : Heap::FunctionObject(scope)
- , index(index)
+inline void
+Heap::ArgumentsSetterFunction::init(QV4::ExecutionContext *scope, uint index)
{
+ Heap::FunctionObject::init(scope);
+ this->index = index;
}
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 34c7746684..23075aa78c 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -46,9 +46,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArrayBufferCtor);
DEFINE_OBJECT_VTABLE(ArrayBuffer);
-Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("ArrayBuffer"))
+void Heap::ArrayBufferCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("ArrayBuffer"));
}
void ArrayBufferCtor::construct(const Managed *m, Scope &scope, CallData *callData)
@@ -94,8 +94,9 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
}
-Heap::ArrayBuffer::ArrayBuffer(size_t length)
+void Heap::ArrayBuffer::init(size_t length)
{
+ Object::init();
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
data = 0;
@@ -106,16 +107,18 @@ Heap::ArrayBuffer::ArrayBuffer(size_t length)
memset(data->data(), 0, length + 1);
}
-Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array)
- : data(const_cast<QByteArray&>(array).data_ptr())
+void Heap::ArrayBuffer::init(const QByteArray& array)
{
+ Object::init();
+ data = const_cast<QByteArray&>(array).data_ptr();
data->ref.ref();
}
-Heap::ArrayBuffer::~ArrayBuffer()
+void Heap::ArrayBuffer::destroy()
{
if (!data->ref.deref())
QTypedArrayData<char>::deallocate(data);
+ Object::destroy();
}
QByteArray ArrayBuffer::asByteArray() const
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index b552cef9f1..bc56d1ea31 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -60,13 +60,13 @@ namespace QV4 {
namespace Heap {
struct ArrayBufferCtor : FunctionObject {
- ArrayBufferCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object {
- ArrayBuffer(size_t length);
- ArrayBuffer(const QByteArray& array);
- ~ArrayBuffer();
+ void init(size_t length);
+ void init(const QByteArray& array);
+ void destroy();
QTypedArrayData<char> *data;
uint byteLength() const { return data->size; }
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 74c83b1940..bfeb3d4699 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -46,6 +46,8 @@
using namespace QV4;
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON
+
const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
QV4::ArrayData::IsExecutionContext,
@@ -94,13 +96,15 @@ const ArrayVTable SparseArrayData::static_vtbl =
SparseArrayData::length
};
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
+
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
{
Value v;
- v.setTagValue(Value::fromReturnedValue(*target).tag(), value);
+ v.setEmpty(value);
*target = v.asReturnedValue();
}
@@ -189,6 +193,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
} else {
sparse->sparse = new SparseArray;
lastFree = &sparse->freeList;
+ storeValue(lastFree, 0);
for (uint i = 0; i < toCopy; ++i) {
if (!sparse->arrayData[i].isEmpty()) {
SparseArrayNode *n = sparse->sparse->insert(i);
@@ -209,6 +214,8 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
}
storeValue(lastFree, UINT_MAX);
}
+
+ Q_ASSERT(Value::fromReturnedValue(sparse->freeList).isEmpty());
// ### Could explicitly free the old data
}
@@ -357,12 +364,12 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->arrayData + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
- v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
- v[0].setTagValue(Value::Empty_Type, idx + 1);
+ v[1].setEmpty(Value::fromReturnedValue(d->freeList).emptyValue());
+ v[0].setEmpty(idx + 1);
} else {
- v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
+ v->setEmpty(Value::fromReturnedValue(d->freeList).emptyValue());
}
- d->freeList = idx;
+ d->freeList = Primitive::emptyValue(idx).asReturnedValue();
if (d->attrs)
d->attrs[idx].clear();
}
@@ -400,9 +407,9 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
// found two slots in a row
- uint idx = Value::fromReturnedValue(*last).uint_32();
+ uint idx = Value::fromReturnedValue(*last).emptyValue();
Value lastV = Value::fromReturnedValue(*last);
- lastV.setTagValue(lastV.tag(), dd->arrayData[lastV.value() + 1].value());
+ lastV.setEmpty(dd->arrayData[lastV.emptyValue() + 1].value());
*last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;
@@ -416,7 +423,8 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
}
uint idx = Value::fromReturnedValue(dd->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->arrayData[idx].uint_32();
+ dd->freeList = dd->arrayData[idx].asReturnedValue();
+ Q_ASSERT(Value::fromReturnedValue(dd->freeList).isEmpty());
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -471,13 +479,14 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
- dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1);
+ dd->arrayData[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
+ dd->arrayData[pidx].setEmpty(pidx + 1);
} else {
- dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
+ Q_ASSERT(dd->type == Heap::ArrayData::Sparse);
+ dd->arrayData[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
}
- dd->freeList = pidx;
+ dd->freeList = Primitive::emptyValue(pidx).asReturnedValue();
dd->sparse->erase(n);
return true;
}
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index d7ee4798b0..24b948f01e 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -133,7 +133,7 @@ struct ArrayData : public Base {
}
};
-Q_STATIC_ASSERT(std::is_trivial<ArrayData>::value);
+V4_ASSERT_IS_TRIVIAL(ArrayData)
struct SimpleArrayData : public ArrayData {
uint mappedIndex(uint index) const { return (index + offset) % alloc; }
@@ -153,10 +153,13 @@ struct SimpleArrayData : public ArrayData {
return attrs ? attrs[i] : Attr_Data;
}
};
-Q_STATIC_ASSERT(std::is_trivial<SimpleArrayData>::value);
+V4_ASSERT_IS_TRIVIAL(SimpleArrayData)
struct SparseArrayData : public ArrayData {
- inline ~SparseArrayData();
+ void destroy() {
+ delete sparse;
+ ArrayData::destroy();
+ }
uint mappedIndex(uint index) const {
SparseArrayNode *n = sparse->findNode(index);
@@ -287,11 +290,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
namespace Heap {
-inline SparseArrayData::~SparseArrayData()
-{
- delete sparse;
-}
-
void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
{
Property *pd = getProperty(index);
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 4d15c6c137..659ede7552 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -49,9 +49,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArrayCtor);
-Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Array"))
+void Heap::ArrayCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Array"));
}
void ArrayCtor::construct(const Managed *m, Scope &scope, CallData *callData)
@@ -186,6 +186,10 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
{
Scope scope(ctx);
ScopedValue arg(scope, ctx->argument(0));
+ ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine));
+
+ if (!instance)
+ return ctx->d()->engine->newString()->asReturnedValue();
QString r4;
if (arg->isUndefined())
@@ -193,8 +197,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
else
r4 = arg->toQString();
- ScopedObject self(scope, ctx->thisObject());
- ScopedValue length(scope, self->get(ctx->d()->engine->id_length()));
+ ScopedValue length(scope, instance->get(ctx->d()->engine->id_length()));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
@@ -203,7 +206,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
QString R;
// ### FIXME
- if (ArrayObject *a = self->as<ArrayObject>()) {
+ if (ArrayObject *a = instance->as<ArrayObject>()) {
ScopedValue e(scope);
for (uint i = 0; i < a->getLength(); ++i) {
if (i)
@@ -220,7 +223,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
// crazy!
//
ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0")));
- ScopedValue r6(scope, self->get(name));
+ ScopedValue r6(scope, instance->get(name));
if (!r6->isNullOrUndefined())
R = r6->toQString();
@@ -229,7 +232,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
R += r4;
name = Primitive::fromDouble(k).toString(scope.engine);
- r12 = self->get(name);
+ r12 = instance->get(name);
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index f49ed76b02..9a05bb8681 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -61,7 +61,7 @@ namespace QV4 {
namespace Heap {
struct ArrayCtor : FunctionObject {
- ArrayCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 57c54e15c4..8047993266 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -45,9 +45,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(BooleanCtor);
DEFINE_OBJECT_VTABLE(BooleanObject);
-Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Boolean"))
+void Heap::BooleanCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Boolean"));
}
void BooleanCtor::construct(const Managed *, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 17543e33e0..4c2f3c09e7 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -61,7 +61,7 @@ namespace QV4 {
namespace Heap {
struct BooleanCtor : FunctionObject {
- BooleanCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index ffedf737ce..0b42288ccc 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -128,7 +128,7 @@ struct ExecutionContext : Base {
bool strictMode : 8;
int lineNumber;
};
-Q_STATIC_ASSERT(std::is_trivial<ExecutionContext>::value);
+V4_ASSERT_IS_TRIVIAL(ExecutionContext)
struct CallContext : ExecutionContext {
static CallContext createOnStack(ExecutionEngine *v4);
@@ -145,20 +145,20 @@ struct CallContext : ExecutionContext {
Value *locals;
Pointer<Object> activation;
};
-Q_STATIC_ASSERT(std::is_trivial<CallContext>::value);
+V4_ASSERT_IS_TRIVIAL(CallContext)
struct GlobalContext : ExecutionContext {
void init(ExecutionEngine *engine);
Pointer<Object> global;
};
-Q_STATIC_ASSERT(std::is_trivial<GlobalContext>::value);
+V4_ASSERT_IS_TRIVIAL(GlobalContext)
struct CatchContext : ExecutionContext {
void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
Pointer<String> exceptionVarName;
Value exceptionValue;
};
-Q_STATIC_ASSERT(std::is_trivial<CatchContext>::value);
+V4_ASSERT_IS_TRIVIAL(CatchContext)
struct WithContext : ExecutionContext {
void init(ExecutionContext *outerContext, Object *with)
@@ -175,7 +175,7 @@ struct WithContext : ExecutionContext {
Pointer<Object> withObject;
};
-Q_STATIC_ASSERT(std::is_trivial<WithContext>::value);
+V4_ASSERT_IS_TRIVIAL(WithContext)
struct QmlContextWrapper;
diff --git a/src/qml/jsruntime/qv4context_p_p.h b/src/qml/jsruntime/qv4context_p_p.h
index 0da9f678ed..ca8dc0b518 100644
--- a/src/qml/jsruntime/qv4context_p_p.h
+++ b/src/qml/jsruntime/qv4context_p_p.h
@@ -69,7 +69,7 @@ QObject *QmlContext::qmlScope() const
QQmlContextData *QmlContext::qmlContext() const
{
- return d()->qml->context;
+ return *d()->qml->context;
}
void QmlContext::takeContextOwnership() {
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index fac3d5316c..db8376272d 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -49,9 +49,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(DataViewCtor);
DEFINE_OBJECT_VTABLE(DataView);
-Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("DataView"))
+void Heap::DataViewCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("DataView"));
}
void DataViewCtor::construct(const Managed *, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index f996a4c2f1..246124394a 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -60,11 +60,11 @@ namespace QV4 {
namespace Heap {
struct DataViewCtor : FunctionObject {
- DataViewCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct DataView : Object {
- DataView() {}
+ void init() { Object::init(); }
Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 04358fe3b5..4f3138a452 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -634,13 +634,15 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-Heap::DateObject::DateObject(const QDateTime &date)
+void Heap::DateObject::init(const QDateTime &date)
{
+ Object::init();
this->date = date.isValid() ? date.toMSecsSinceEpoch() : qt_qnan();
}
-Heap::DateObject::DateObject(const QTime &time)
+void Heap::DateObject::init(const QTime &time)
{
+ Object::init();
if (!time.isValid()) {
date = qt_qnan();
return;
@@ -668,9 +670,9 @@ QDateTime DateObject::toQDateTime() const
DEFINE_OBJECT_VTABLE(DateCtor);
-Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Date"))
+void Heap::DateCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Date"));
}
void DateCtor::construct(const Managed *, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index c67acdcfa2..2d0648396e 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -63,24 +63,26 @@ namespace QV4 {
namespace Heap {
struct DateObject : Object {
- DateObject()
+ void init()
{
+ Object::init();
date = qt_qnan();
}
- DateObject(const Value &date)
+ void init(const Value &date)
{
+ Object::init();
this->date = date.toNumber();
}
- DateObject(const QDateTime &date);
- double date;
+ void init(const QDateTime &date);
+ void init(const QTime &time);
- DateObject(const QTime &time);
+ double date;
};
struct DateCtor : FunctionObject {
- DateCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index fea6bbbd70..7265952f72 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -86,7 +86,9 @@
#include "qv4isel_masm_p.h"
#endif // V4_ENABLE_JIT
+#if QT_CONFIG(qml_interpreter)
#include "qv4isel_moth_p.h"
+#endif
#if USE(PTHREADS)
# include <pthread.h>
@@ -160,6 +162,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
MemoryManager::GCBlocker gcBlocker(memoryManager);
if (!factory) {
+#if QT_CONFIG(qml_interpreter)
bool jitDisabled = true;
#ifdef V4_ENABLE_JIT
@@ -180,6 +183,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
"very slow. Visit https://wiki.qt.io/V4 to learn about possible "
"solutions for your platform.");
}
+#else
+ factory = new JIT::ISelFactory;
+#endif
}
iselFactory.reset(factory);
@@ -744,7 +750,7 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const
if (!ctx)
return 0;
- return ctx->qml->context.contextData();
+ return ctx->qml->context->contextData();
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -920,7 +926,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
QV4::Scope scope(this);
QV4::Scoped<ErrorObject> error(scope, value);
if (!!error)
- exceptionStackTrace = error->d()->stackTrace;
+ exceptionStackTrace = *error->d()->stackTrace;
else
exceptionStackTrace = stackTrace();
@@ -1079,7 +1085,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
QV4::Scope scope(e);
if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
- return v->d()->data;
+ return v->d()->data();
if (typeHint == QVariant::Bool)
return QVariant(value.toBoolean());
@@ -1153,7 +1159,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return str;
}
if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
- return ld->d()->locale;
+ return *ld->d()->locale;
if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
if (const ArrayBuffer *d = value.as<ArrayBuffer>())
@@ -1693,7 +1699,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
return true;
if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value->as<QV4::VariantObject>()->d()->data;
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data();
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
@@ -1705,7 +1711,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
- const QVariant &v = vo->d()->data;
+ const QVariant &v = vo->d()->data();
canCast = (type == v.userType()) || (valueType && (valueType == v.userType()));
}
else if (proto->as<QV4::QObjectWrapper>()) {
@@ -1760,7 +1766,7 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const Value &value)
QV4::Scoped<QV4::VariantObject> v(scope, value);
if (v) {
- QVariant variant = v->d()->data;
+ QVariant variant = v->d()->data();
int type = variant.userType();
if (type == QMetaType::QObjectStar)
return *reinterpret_cast<QObject* const *>(variant.constData());
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 3763bf2613..597ded6ae1 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -67,8 +67,11 @@
using namespace QV4;
-Heap::ErrorObject::ErrorObject()
+void Heap::ErrorObject::init()
{
+ Object::init();
+ stackTrace = nullptr;
+
Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
@@ -81,8 +84,9 @@ Heap::ErrorObject::ErrorObject()
*propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined();
}
-Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t)
+void Heap::ErrorObject::init(const Value &message, ErrorType t)
{
+ Object::init();
errorType = t;
Scope scope(internalClass->engine);
@@ -91,18 +95,19 @@ Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t)
*propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
*propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
- e->d()->stackTrace = scope.engine->stackTrace();
- if (!e->d()->stackTrace.isEmpty()) {
- *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
+ e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
+ if (!e->d()->stackTrace->isEmpty()) {
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line);
}
if (!message.isUndefined())
*propertyData(QV4::ErrorObject::Index_Message) = message;
}
-Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
+void Heap::ErrorObject::init(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
{
+ Object::init();
errorType = t;
Scope scope(internalClass->engine);
@@ -111,16 +116,16 @@ Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, in
*propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
*propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
- e->d()->stackTrace = scope.engine->stackTrace();
+ e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
StackFrame frame;
frame.source = fileName;
frame.line = line;
frame.column = column;
- e->d()->stackTrace.prepend(frame);
+ e->d()->stackTrace->prepend(frame);
- if (!e->d()->stackTrace.isEmpty()) {
- *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
+ if (!e->d()->stackTrace->isEmpty()) {
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line);
}
if (!message.isUndefined())
@@ -156,10 +161,10 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
return ctx->engine()->throwTypeError();
if (!This->d()->stack) {
QString trace;
- for (int i = 0; i < This->d()->stackTrace.count(); ++i) {
+ for (int i = 0; i < This->d()->stackTrace->count(); ++i) {
if (i > 0)
trace += QLatin1Char('\n');
- const StackFrame &frame = This->d()->stackTrace[i];
+ const StackFrame &frame = This->d()->stackTrace->at(i);
trace += frame.function + QLatin1Char('@') + frame.source;
if (frame.line >= 0)
trace += QLatin1Char(':') + QString::number(frame.line);
@@ -181,44 +186,44 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
-Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg)
- : Heap::ErrorObject(msg, SyntaxError)
+void Heap::SyntaxErrorObject::init(const Value &msg)
{
+ Heap::ErrorObject::init(msg, SyntaxError);
}
-Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, SyntaxError)
+void Heap::SyntaxErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
{
+ Heap::ErrorObject::init(msg, fileName, lineNumber, columnNumber, SyntaxError);
}
-Heap::EvalErrorObject::EvalErrorObject(const Value &message)
- : Heap::ErrorObject(message, EvalError)
+void Heap::EvalErrorObject::init(const Value &message)
{
+ Heap::ErrorObject::init(message, EvalError);
}
-Heap::RangeErrorObject::RangeErrorObject(const Value &message)
- : Heap::ErrorObject(message, RangeError)
+void Heap::RangeErrorObject::init(const Value &message)
{
+ Heap::ErrorObject::init(message, RangeError);
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &message)
- : Heap::ErrorObject(message, ReferenceError)
+void Heap::ReferenceErrorObject::init(const Value &message)
{
+ Heap::ErrorObject::init(message, ReferenceError);
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, ReferenceError)
+void Heap::ReferenceErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
{
+ Heap::ErrorObject::init(msg, fileName, lineNumber, columnNumber, ReferenceError);
}
-Heap::TypeErrorObject::TypeErrorObject(const Value &message)
- : Heap::ErrorObject(message, TypeError)
+void Heap::TypeErrorObject::init(const Value &message)
{
+ Heap::ErrorObject::init(message, TypeError);
}
-Heap::URIErrorObject::URIErrorObject(const Value &message)
- : Heap::ErrorObject(message, URIError)
+void Heap::URIErrorObject::init(const Value &message)
{
+ Heap::ErrorObject::init(message, URIError);
}
DEFINE_OBJECT_VTABLE(ErrorCtor);
@@ -229,14 +234,14 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor);
DEFINE_OBJECT_VTABLE(TypeErrorCtor);
DEFINE_OBJECT_VTABLE(URIErrorCtor);
-Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Error"))
+void Heap::ErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Error"));
}
-Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name)
- : Heap::FunctionObject(scope, name)
+void Heap::ErrorCtor::init(QV4::ExecutionContext *scope, const QString &name)
{
+ Heap::FunctionObject::init(scope, name);
}
void ErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
@@ -250,9 +255,9 @@ void ErrorCtor::call(const Managed *that, Scope &scope, CallData *callData)
static_cast<const Object *>(that)->construct(scope, callData);
}
-Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
- : Heap::ErrorCtor(scope, QStringLiteral("EvalError"))
+void Heap::EvalErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::ErrorCtor::init(scope, QStringLiteral("EvalError"));
}
void EvalErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
@@ -261,9 +266,9 @@ void EvalErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
scope.result = ErrorObject::create<EvalErrorObject>(scope.engine, v);
}
-Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
- : Heap::ErrorCtor(scope, QStringLiteral("RangeError"))
+void Heap::RangeErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::ErrorCtor::init(scope, QStringLiteral("RangeError"));
}
void RangeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
@@ -272,9 +277,9 @@ void RangeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData
scope.result = ErrorObject::create<RangeErrorObject>(scope.engine, v);
}
-Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
- : Heap::ErrorCtor(scope, QStringLiteral("ReferenceError"))
+void Heap::ReferenceErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::ErrorCtor::init(scope, QStringLiteral("ReferenceError"));
}
void ReferenceErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
@@ -283,9 +288,9 @@ void ReferenceErrorCtor::construct(const Managed *, Scope &scope, CallData *call
scope.result = ErrorObject::create<ReferenceErrorObject>(scope.engine, v);
}
-Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
- : Heap::ErrorCtor(scope, QStringLiteral("SyntaxError"))
+void Heap::SyntaxErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::ErrorCtor::init(scope, QStringLiteral("SyntaxError"));
}
void SyntaxErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
@@ -294,9 +299,9 @@ void SyntaxErrorCtor::construct(const Managed *, Scope &scope, CallData *callDat
scope.result = ErrorObject::create<SyntaxErrorObject>(scope.engine, v);
}
-Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
- : Heap::ErrorCtor(scope, QStringLiteral("TypeError"))
+void Heap::TypeErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::ErrorCtor::init(scope, QStringLiteral("TypeError"));
}
void TypeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
@@ -305,9 +310,9 @@ void TypeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
scope.result = ErrorObject::create<TypeErrorObject>(scope.engine, v);
}
-Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
- : Heap::ErrorCtor(scope, QStringLiteral("URIError"))
+void Heap::URIErrorCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::ErrorCtor::init(scope, QStringLiteral("URIError"));
}
void URIErrorCtor::construct(const Managed *, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 42a3d05d9f..42a6e0b4b1 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -73,68 +73,72 @@ struct ErrorObject : Object {
URIError
};
- ErrorObject();
- ErrorObject(const Value &message, ErrorType t = Error);
- ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ void init();
+ void init(const Value &message, ErrorType t = Error);
+ void init(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ void destroy() {
+ delete stackTrace;
+ Object::destroy();
+ }
ErrorType errorType;
- StackTrace stackTrace;
+ StackTrace *stackTrace;
Pointer<String> stack;
};
struct EvalErrorObject : ErrorObject {
- EvalErrorObject(const Value &message);
+ void init(const Value &message);
};
struct RangeErrorObject : ErrorObject {
- RangeErrorObject(const Value &message);
+ void init(const Value &message);
};
struct ReferenceErrorObject : ErrorObject {
- ReferenceErrorObject(const Value &message);
- ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
+ void init(const Value &message);
+ void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct SyntaxErrorObject : ErrorObject {
- SyntaxErrorObject(const Value &message);
- SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
+ void init(const Value &message);
+ void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct TypeErrorObject : ErrorObject {
- TypeErrorObject(const Value &message);
+ void init(const Value &message);
};
struct URIErrorObject : ErrorObject {
- URIErrorObject(const Value &message);
+ void init(const Value &message);
};
struct ErrorCtor : Heap::FunctionObject {
- ErrorCtor(QV4::ExecutionContext *scope);
- ErrorCtor(QV4::ExecutionContext *scope, const QString &name);
+ void init(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope, const QString &name);
};
struct EvalErrorCtor : ErrorCtor {
- EvalErrorCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct RangeErrorCtor : ErrorCtor {
- RangeErrorCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct ReferenceErrorCtor : ErrorCtor {
- ReferenceErrorCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct SyntaxErrorCtor : ErrorCtor {
- SyntaxErrorCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct TypeErrorCtor : ErrorCtor {
- TypeErrorCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct URIErrorCtor : ErrorCtor {
- URIErrorCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 300e538d3d..caabee322a 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -73,7 +73,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
}
// duplicate arguments, need some trick to store them
MemoryManager *mm = engine->memoryManager;
- arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)), true);
+ arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)));
}
}
nFormals = compiledFunction->nFormals;
@@ -105,7 +105,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
break;
}
// duplicate arguments, need some trick to store them
- arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)), true);
+ arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)));
}
}
nFormals = parameters.size();
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index e160dd8a36..2cc58b74a6 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -68,18 +68,20 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
-Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
{
+ Object::init();
+ function = nullptr;
this->scope = scope->d();
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
f->init(name, createProto);
}
-Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, bool createProto)
{
+ Object::init();
+ function = nullptr;
this->scope = scope->d();
Scope s(scope->engine());
ScopedString name(s, function->name());
@@ -87,9 +89,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun
f->init(name, createProto);
}
-Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name, bool createProto)
{
+ Object::init();
+ function = nullptr;
this->scope = scope->d();
Scope s(scope->engine());
ScopedFunctionObject f(s, this);
@@ -97,9 +100,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString
f->init(n, createProto);
}
-Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init(ExecutionContext *scope, const QString &name, bool createProto)
{
+ Object::init();
+ function = nullptr;
this->scope = scope;
Scope s(scope->engine);
ScopedFunctionObject f(s, this);
@@ -107,9 +111,10 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam
f->init(n, createProto);
}
-Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const ReturnedValue name)
{
+ Object::init();
+ function = nullptr;
this->scope = scope->d();
Scope s(scope);
ScopedFunctionObject f(s, this);
@@ -117,9 +122,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne
f->init(n, false);
}
-Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init(ExecutionContext *scope, const ReturnedValue name)
{
+ Object::init();
+ function = nullptr;
this->scope = scope;
Scope s(scope->engine);
ScopedFunctionObject f(s, this);
@@ -127,19 +133,21 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
f->init(n, false);
}
-Heap::FunctionObject::FunctionObject()
- : function(Q_NULLPTR)
+void Heap::FunctionObject::init()
{
+ Object::init();
+ function = nullptr;
this->scope = internalClass->engine->rootContext()->d();
Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
*propertyData(Index_Prototype) = Encode::undefined();
}
-Heap::FunctionObject::~FunctionObject()
+void Heap::FunctionObject::destroy()
{
if (function)
function->compilationUnit->release();
+ Object::destroy();
}
void FunctionObject::init(String *n, bool createProto)
@@ -227,7 +235,7 @@ QQmlSourceLocation FunctionObject::sourceLocation() const
{
if (isBinding()) {
Q_ASSERT(as<const QV4::QQmlBindingFunction>());
- return static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation;
+ return *static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation;
}
QV4::Function *function = d()->function;
Q_ASSERT(function);
@@ -237,9 +245,9 @@ QQmlSourceLocation FunctionObject::sourceLocation() const
DEFINE_OBJECT_VTABLE(FunctionCtor);
-Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Function"))
+void Heap::FunctionCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Function"));
}
// 15.3.2
@@ -305,8 +313,9 @@ void FunctionCtor::call(const Managed *that, Scope &scope, CallData *callData)
DEFINE_OBJECT_VTABLE(FunctionPrototype);
-Heap::FunctionPrototype::FunctionPrototype()
+void Heap::FunctionPrototype::init()
{
+ Heap::FunctionObject::init();
}
void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
@@ -417,9 +426,9 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
DEFINE_OBJECT_VTABLE(ScriptFunction);
-Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *function)
- : Heap::SimpleScriptFunction(scope, function, true)
+void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function)
{
+ Heap::SimpleScriptFunction::init(scope, function, true);
}
void ScriptFunction::construct(const Managed *that, Scope &scope, CallData *callData)
@@ -478,8 +487,9 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
-Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
+void Heap::SimpleScriptFunction::init(QV4::ExecutionContext *scope, Function *function, bool createProto)
{
+ FunctionObject::init();
this->scope = scope->d();
this->function = function;
@@ -599,10 +609,10 @@ Heap::Object *SimpleScriptFunction::protoForConstructor()
DEFINE_OBJECT_VTABLE(BuiltinFunction);
-Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *))
- : Heap::FunctionObject(scope, name)
- , code(code)
+void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *))
{
+ Heap::FunctionObject::init(scope, name);
+ this->code = code;
}
void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *)
@@ -656,10 +666,10 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
DEFINE_OBJECT_VTABLE(BoundFunction);
-Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target,
- const Value &boundThis, QV4::MemberData *boundArgs)
- : Heap::FunctionObject(scope, QStringLiteral("__bound function__"))
+void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target,
+ const Value &boundThis, QV4::MemberData *boundArgs)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("__bound function__"));
this->target = target->d();
this->boundArgs = boundArgs ? boundArgs->d() : 0;
this->boundThis = boundThis;
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 182b762606..e58b83e2c3 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -69,14 +69,14 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
Index_ProtoConstructor = 0
};
- FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false);
- FunctionObject(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false);
- FunctionObject(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
- FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
- FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name);
- FunctionObject(ExecutionContext *scope, const ReturnedValue name);
- FunctionObject();
- ~FunctionObject();
+ void init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false);
+ void init(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false);
+ void init(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
+ void init(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
+ void init(QV4::ExecutionContext *scope, const ReturnedValue name);
+ void init(ExecutionContext *scope, const ReturnedValue name);
+ void init();
+ void destroy();
unsigned int formalParameterCount() { return function ? function->nFormals : 0; }
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
@@ -87,20 +87,20 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
};
struct FunctionCtor : FunctionObject {
- FunctionCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
struct FunctionPrototype : FunctionObject {
- FunctionPrototype();
+ void init();
};
struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
- BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *));
+ void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *));
ReturnedValue (*code)(QV4::CallContext *);
};
struct IndexedBuiltinFunction : FunctionObject {
- inline IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index));
+ inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index));
ReturnedValue (*code)(QV4::CallContext *, uint index);
uint index;
};
@@ -110,15 +110,15 @@ struct SimpleScriptFunction : FunctionObject {
Index_Name = FunctionObject::Index_Prototype + 1,
Index_Length
};
- SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto);
+ void init(QV4::ExecutionContext *scope, Function *function, bool createProto);
};
struct ScriptFunction : SimpleScriptFunction {
- ScriptFunction(QV4::ExecutionContext *scope, Function *function);
+ void init(QV4::ExecutionContext *scope, Function *function);
};
struct BoundFunction : FunctionObject {
- BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
+ void init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
Pointer<FunctionObject> target;
Value boundThis;
Pointer<MemberData> boundArgs;
@@ -216,12 +216,12 @@ struct IndexedBuiltinFunction: FunctionObject
static void call(const Managed *that, Scope &scope, CallData *callData);
};
-Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index,
- ReturnedValue (*code)(QV4::CallContext *ctx, uint index))
- : Heap::FunctionObject(scope),
- code(code)
- , index(index)
+void Heap::IndexedBuiltinFunction::init(QV4::ExecutionContext *scope, uint index,
+ ReturnedValue (*code)(QV4::CallContext *ctx, uint index))
{
+ Heap::FunctionObject::init(scope);
+ this->index = index;
+ this->code = code;
}
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index b88e271a26..feb0d90d26 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -330,9 +330,9 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
-Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval())
+void Heap::EvalFunction::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, scope->d()->engine->id_eval());
Scope s(scope);
ScopedFunctionObject f(s, this);
f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 403639f8c1..e8b3a92d34 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -60,7 +60,7 @@ namespace QV4 {
namespace Heap {
struct EvalFunction : FunctionObject {
- EvalFunction(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index c33d2cad11..be8057e9f5 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -41,7 +41,7 @@
#include "qv4scopedvalue_p.h"
#include <QtQml/qjsengine.h>
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
#endif
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
QV4::QmlContext *qmlContext, const QV4::Value &callback)
: v4(engine), m_url(url)
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
, m_redirectCount(0), m_network(0) , m_reply(0)
#endif
{
@@ -71,7 +71,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
m_resultObject.set(v4, resultValue(v4));
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
m_network = engine->v8Engine->networkAccessManager();
QNetworkRequest request;
@@ -86,7 +86,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
QV4Include::~QV4Include()
{
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
delete m_reply;
m_reply = 0;
#endif
@@ -135,7 +135,7 @@ QV4::ReturnedValue QV4Include::result()
#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
void QV4Include::finished()
{
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
m_redirectCount++;
if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
@@ -184,7 +184,7 @@ void QV4Include::finished()
QV4::ScopedObject resultObj(scope, m_resultObject.value());
QV4::ScopedString status(scope, v4->newString(QStringLiteral("status")));
resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
-#endif //QT_NO_NETWORK
+#endif // qml_network
QV4::ScopedValue cb(scope, m_callbackFunction.value());
callback(cb, resultObj);
@@ -211,7 +211,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
callbackFunction = ctx->args()[1];
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 1750e6a7e1..4c601a5e7b 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -62,7 +62,7 @@
QT_BEGIN_NAMESPACE
class QQmlEngine;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
class QNetworkAccessManager;
#endif
class QNetworkReply;
@@ -94,7 +94,7 @@ private:
QV4::ExecutionEngine *v4;
QUrl m_url;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
int m_redirectCount;
QNetworkAccessManager *m_network;
QPointer<QNetworkReply> m_reply;
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index bac45e18c8..d17da9af0c 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -132,16 +132,20 @@ static void insertHoleIntoPropertyData(Object *object, int idx)
int icSize = object->internalClass()->size;
int from = qMax(idx, inlineSize);
int to = from + 1;
- if (from < icSize)
- memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1);
+ if (from < icSize) {
+ memmove(object->propertyData(to), object->propertyData(from),
+ (icSize - from - 1) * sizeof(Value));
+ }
if (from == idx)
return;
if (inlineSize < icSize)
*object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1);
from = idx;
to = from + 1;
- if (from < inlineSize - 1)
- memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1);
+ if (from < inlineSize - 1) {
+ memmove(object->propertyData(to), object->propertyData(from),
+ (inlineSize - from - 1) * sizeof(Value));
+ }
}
static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 5b665d8836..94a6e4daa1 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -44,6 +44,7 @@
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4runtime_p.h>
+#include <qv4variantobject_p.h>
#include "qv4string_p.h"
#include <qstack.h>
@@ -734,6 +735,10 @@ QString Stringify::Str(const QString &key, const Value &v)
return std::isfinite(d) ? scope.result.toQString() : QStringLiteral("null");
}
+ if (const QV4::VariantObject *v = scope.result.as<QV4::VariantObject>()) {
+ return v->d()->data().toString();
+ }
+
o = scope.result.asReturnedValue();
if (o) {
if (!o->as<FunctionObject>()) {
@@ -867,8 +872,9 @@ QString Stringify::JA(ArrayObject *a)
}
-Heap::JsonObject::JsonObject()
+void Heap::JsonObject::init()
{
+ Object::init();
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index c3a3b191c0..43248a214d 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -64,7 +64,7 @@ namespace QV4 {
namespace Heap {
struct JsonObject : Object {
- JsonObject();
+ void init();
};
}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 764a8e7f3f..1fff5a45da 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -74,7 +74,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
#define V4_MANAGED_SIZE_TEST
#endif
-#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->~Data(); }
+#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->destroy(); }
#define V4_MANAGED_ITSELF(DataClass, superClass) \
@@ -88,9 +88,10 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
QV4::Heap::DataClass *d() const { \
QV4::Heap::DataClass *dptr = d_unchecked(); \
- if (std::is_trivial<QV4::Heap::DataClass>::value) dptr->_checkIsInitialized(); \
+ dptr->_checkIsInitialized(); \
return dptr; \
- }
+ } \
+ V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass)
#define V4_MANAGED(DataClass, superClass) \
private: \
@@ -105,6 +106,18 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
#define Q_VTABLE_FUNCTION(classname, func) \
(classname::func == QV4::Managed::func ? 0 : classname::func)
+// Q_VTABLE_FUNCTION triggers a bogus tautological-compare warning in GCC6+
+#if defined(Q_CC_GNU) && Q_CC_GNU >= 600
+#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
+ QT_WARNING_PUSH; \
+ QT_WARNING_DISABLE_GCC("-Wtautological-compare")
+
+#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \
+ ;QT_WARNING_POP
+#else
+#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON
+#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
+#endif
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
@@ -124,7 +137,9 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
}
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) \
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
struct Q_QML_PRIVATE_EXPORT Managed : Value
{
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 9fe8224736..e03b2762cc 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -51,8 +51,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(MathObject);
-Heap::MathObject::MathObject()
+void Heap::MathObject::init()
{
+ Object::init();
Scope scope(internalClass->engine);
ScopedObject m(scope, this);
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 01e778d9ec..f6b1a4395f 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -59,7 +59,7 @@ namespace QV4 {
namespace Heap {
struct MathObject : Object {
- MathObject();
+ void init();
};
}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 41da730428..969eee3619 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -66,7 +66,7 @@ struct MemberData : Base {
};
Value data[1];
};
-Q_STATIC_ASSERT(std::is_trivial<MemberData>::value);
+V4_ASSERT_IS_TRIVIAL(MemberData)
}
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 444a4cd6f0..9b1f72bc17 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -73,9 +73,9 @@ const NumberLocale *NumberLocale::instance()
return numberLocaleHolder();
}
-Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Number"))
+void Heap::NumberCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Number"));
}
void NumberCtor::construct(const Managed *, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 2416165c78..6022b3a029 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -61,7 +61,7 @@ namespace QV4 {
namespace Heap {
struct NumberCtor : FunctionObject {
- NumberCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index aeb185049f..00e6d230da 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -1160,10 +1160,10 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
-Heap::ArrayObject::ArrayObject(const QStringList &list)
- : Heap::Object()
+void Heap::ArrayObject::init(const QStringList &list)
{
- init();
+ Object::init();
+ commonInit();
Scope scope(internalClass->engine);
ScopedObject a(scope, this);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 54ce2ea60d..d5195adaf0 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -68,7 +68,8 @@ namespace QV4 {
namespace Heap {
struct Object : Base {
- inline Object() { Base::init(); }
+ void init() { Base::init(); }
+ void destroy() { Base::destroy(); }
const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
@@ -93,9 +94,10 @@ struct Object : Base {
Data *d_unchecked() const { return static_cast<Data *>(m()); } \
Data *d() const { \
Data *dptr = d_unchecked(); \
- if (std::is_trivial<Data>::value) dptr->_checkIsInitialized(); \
+ dptr->_checkIsInitialized(); \
return dptr; \
- }
+ } \
+ V4_ASSERT_IS_TRIVIAL(Data);
#define V4_OBJECT2(DataClass, superClass) \
private: \
@@ -111,9 +113,10 @@ struct Object : Base {
QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
QV4::Heap::DataClass *d() const { \
QV4::Heap::DataClass *dptr = d_unchecked(); \
- if (std::is_trivial<QV4::Heap::DataClass>::value) dptr->_checkIsInitialized(); \
+ dptr->_checkIsInitialized(); \
return dptr; \
- }
+ } \
+ V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass);
#define V4_INTERNALCLASS(c) \
static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \
@@ -141,7 +144,7 @@ struct ObjectVTable
void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
-#define DEFINE_OBJECT_VTABLE(classname) \
+#define DEFINE_OBJECT_VTABLE_BASE(classname) \
const QV4::ObjectVTable classname::static_vtbl = \
{ \
DEFINE_MANAGED_VTABLE_INT(classname, (QT_PREPEND_NAMESPACE(QtPrivate)::is_same<classname::SuperClass, Object>::value) ? Q_NULLPTR : &classname::SuperClass::static_vtbl.vTable), \
@@ -161,7 +164,15 @@ const QV4::ObjectVTable classname::static_vtbl = \
advanceIterator \
}
+#define DEFINE_OBJECT_VTABLE(classname) \
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
+DEFINE_OBJECT_VTABLE_BASE(classname) \
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
+#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
+template<> DEFINE_OBJECT_VTABLE_BASE(classname) \
+QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF
struct Q_QML_EXPORT Object: Managed {
V4_OBJECT2(Object, Object)
@@ -375,18 +386,22 @@ private:
namespace Heap {
struct BooleanObject : Object {
- BooleanObject() {}
- BooleanObject(bool b)
- : b(b)
- {}
+ void init() { Object::init(); }
+ void init(bool b) {
+ Object::init();
+ this->b = b;
+ }
+
bool b;
};
struct NumberObject : Object {
- NumberObject() {}
- NumberObject(double val)
- : value(val)
- {}
+ void init() { Object::init(); }
+ void init(double val) {
+ Object::init();
+ value = val;
+ }
+
double value;
};
@@ -395,10 +410,15 @@ struct ArrayObject : Object {
LengthPropertyIndex = 0
};
- ArrayObject()
- { init(); }
- ArrayObject(const QStringList &list);
- void init()
+ void init() {
+ Object::init();
+ commonInit();
+ }
+
+ void init(const QStringList &list);
+
+private:
+ void commonInit()
{ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); }
};
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 4354e09248..7943a13ac0 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -45,30 +45,6 @@
using namespace QV4;
-ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags)
- : engine(e)
- , object(scratch1)
- , current(scratch2)
- , arrayNode(0)
- , arrayIndex(0)
- , memberIndex(0)
- , flags(flags)
-{
- init(o);
-}
-
-ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags)
- : engine(scope.engine)
- , object(scope.alloc(1))
- , current(scope.alloc(1))
- , arrayNode(0)
- , arrayIndex(0)
- , memberIndex(0)
- , flags(flags)
-{
- init(o);
-}
-
void ObjectIterator::init(const Object *o)
{
object->setM(o ? o->m() : 0);
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 6bef703a4d..98e94a95ea 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Q_QML_EXPORT ObjectIterator
+struct Q_QML_EXPORT ObjectIteratorData
{
enum Flags {
NoFlags = 0,
@@ -72,21 +72,52 @@ struct Q_QML_EXPORT ObjectIterator
uint arrayIndex;
uint memberIndex;
uint flags;
+};
+V4_ASSERT_IS_TRIVIAL(ObjectIteratorData)
+
+struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData
+{
+ ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags)
+ {
+ engine = e;
+ object = scratch1;
+ current = scratch2;
+ arrayNode = nullptr;
+ arrayIndex = 0;
+ memberIndex = 0;
+ this->flags = flags;
+ init(o);
+ }
+
+ ObjectIterator(Scope &scope, const Object *o, uint flags)
+ {
+ engine = scope.engine;
+ object = scope.alloc(1);
+ current = scope.alloc(1);
+ arrayNode = nullptr;
+ arrayIndex = 0;
+ memberIndex = 0;
+ this->flags = flags;
+ init(o);
+ }
- ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags);
- ObjectIterator(Scope &scope, const Object *o, uint flags);
- void init(const Object *o);
void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
ReturnedValue nextPropertyNameAsString();
+
+private:
+ void init(const Object *o);
};
namespace Heap {
struct ForEachIteratorObject : Object {
- ForEachIteratorObject(QV4::Object *o);
- ObjectIterator it;
+ void init(QV4::Object *o);
+ ObjectIterator &it() { return *reinterpret_cast<ObjectIterator*>(&itData); }
Value workArea[2];
+
+private:
+ ObjectIteratorData itData;
};
}
@@ -95,16 +126,18 @@ struct ForEachIteratorObject: Object {
V4_OBJECT2(ForEachIteratorObject, Object)
Q_MANAGED_TYPE(ForeachIteratorObject)
- ReturnedValue nextPropertyName() { return d()->it.nextPropertyNameAsString(); }
+ ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); }
protected:
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
inline
-Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::Object *o)
- : it(internalClass->engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
+void Heap::ForEachIteratorObject::init(QV4::Object *o)
{
+ Object::init();
+ it() = ObjectIterator(internalClass->engine, workArea, workArea + 1, o,
+ ObjectIterator::EnumerableOnly | ObjectIterator::WithProtoChain);
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index cfd76166f2..6020c48250 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -54,9 +54,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ObjectCtor);
-Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("Object"))
+void Heap::ObjectCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("Object"));
}
void ObjectCtor::construct(const Managed *that, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 47a37b196f..e3d85782d5 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -61,7 +61,7 @@ namespace QV4 {
namespace Heap {
struct ObjectCtor : FunctionObject {
- ObjectCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 7ca0692804..a892194df3 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -139,7 +139,7 @@ PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++()
while (p) {
while (index < kEntriesPerPage - 1) {
++index;
- if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type)
+ if (!static_cast<Page *>(p)->values[index].isEmpty())
return *this;
}
index = -1;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index b901d9be85..295b3413da 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -195,8 +195,9 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
}
}
-Heap::QObjectWrapper::QObjectWrapper(QObject *object)
+void Heap::QObjectWrapper::init(QObject *object)
{
+ Object::init();
qObj.init(object);
}
@@ -613,8 +614,14 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
{
- if (engine->jsEngine())
- QQmlData::ensurePropertyCache(engine->jsEngine(), object);
+ if (QJSEngine *jsEngine = engine->jsEngine()) {
+ if (QQmlPropertyCache *cache = QQmlData::ensurePropertyCache(jsEngine, object)) {
+ ReturnedValue result = QV4::Encode::null();
+ void *args[] = { &result, &engine };
+ if (cache->callJSFactoryMethod(object, args))
+ return result;
+ }
+ }
return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue();
}
@@ -978,6 +985,10 @@ void QObjectWrapper::destroyObject(bool lastCall)
delete h->object();
else
h->object()->deleteLater();
+ } else {
+ // If the object is C++-owned, we still have to release the weak reference we have
+ // to it.
+ ddata->jsWrapper.clear();
}
}
}
@@ -1678,7 +1689,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in
method->d()->setObject(object);
if (QQmlData *ddata = QQmlData::get(object))
- method->d()->propertyCache = ddata->propertyCache;
+ method->d()->setPropertyCache(ddata->propertyCache);
method->d()->index = index;
return method.asReturnedValue();
@@ -1688,21 +1699,21 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueType
{
Scope valueScope(scope);
Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope));
- method->d()->propertyCache = valueType->d()->propertyCache;
+ method->d()->setPropertyCache(valueType->d()->propertyCache());
method->d()->index = index;
method->d()->valueTypeWrapper = valueType->d();
return method.asReturnedValue();
}
-Heap::QObjectMethod::QObjectMethod(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope)
+void Heap::QObjectMethod::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope);
}
const QMetaObject *Heap::QObjectMethod::metaObject()
{
- if (propertyCache)
- return propertyCache->createMetaObject();
+ if (propertyCache())
+ return propertyCache()->createMetaObject();
return object()->metaObject();
}
@@ -1774,13 +1785,13 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
return;
}
- object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr);
+ object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr);
}
QQmlPropertyData method;
- if (d()->propertyCache) {
- QQmlPropertyData *data = d()->propertyCache->method(d()->index);
+ if (d()->propertyCache()) {
+ QQmlPropertyData *data = d()->propertyCache()->method(d()->index);
if (!data) {
scope.result = QV4::Encode::undefined();
return;
@@ -1823,7 +1834,7 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
if (!method.isOverload()) {
scope.result = CallPrecise(object, method, v4, callData);
} else {
- scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache);
+ scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache());
}
}
@@ -1839,13 +1850,15 @@ void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
DEFINE_OBJECT_VTABLE(QObjectMethod);
-Heap::QMetaObjectWrapper::QMetaObjectWrapper(const QMetaObject *metaObject)
- : metaObject(metaObject)
- , constructors(nullptr)
- , constructorCount(0)
-{}
+void Heap::QMetaObjectWrapper::init(const QMetaObject *metaObject)
+{
+ FunctionObject::init();
+ this->metaObject = metaObject;
+ constructors = nullptr;
+ constructorCount = 0;
+}
-Heap::QMetaObjectWrapper::~QMetaObjectWrapper()
+void Heap::QMetaObjectWrapper::destroy()
{
delete[] constructors;
}
@@ -2011,9 +2024,10 @@ DEFINE_OBJECT_VTABLE(QMetaObjectWrapper);
-Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex)
- : signalIndex(signalIndex)
+void Heap::QmlSignalHandler::init(QObject *object, int signalIndex)
{
+ Object::init();
+ this->signalIndex = signalIndex;
setObject(object);
}
@@ -2021,7 +2035,7 @@ DEFINE_OBJECT_VTABLE(QmlSignalHandler);
void QmlSignalHandler::initProto(ExecutionEngine *engine)
{
- if (engine->signalHandlerPrototype()->d())
+ if (engine->signalHandlerPrototype()->d_unchecked())
return;
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 076f304fea..8b2fd506e8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -77,9 +77,12 @@ namespace Heap {
struct QQmlValueTypeWrapper;
-struct QObjectWrapper : Object {
- QObjectWrapper(QObject *object);
- ~QObjectWrapper() { qObj.destroy(); }
+struct Q_QML_EXPORT QObjectWrapper : Object {
+ void init(QObject *object);
+ void destroy() {
+ qObj.destroy();
+ Object::destroy();
+ }
QObject *object() const { return qObj.data(); }
@@ -88,10 +91,22 @@ private:
};
struct QObjectMethod : FunctionObject {
- QObjectMethod(QV4::ExecutionContext *scope);
- ~QObjectMethod() { qObj.destroy(); }
- QQmlRefPointer<QQmlPropertyCache> propertyCache;
- int index;
+ void init(QV4::ExecutionContext *scope);
+ void destroy()
+ {
+ setPropertyCache(nullptr);
+ qObj.destroy();
+ FunctionObject::destroy();
+ }
+
+ QQmlPropertyCache *propertyCache() const { return _propertyCache; }
+ void setPropertyCache(QQmlPropertyCache *c) {
+ if (c)
+ c->addref();
+ if (_propertyCache)
+ _propertyCache->release();
+ _propertyCache = c;
+ }
Pointer<QQmlValueTypeWrapper> valueTypeWrapper;
@@ -101,6 +116,10 @@ struct QObjectMethod : FunctionObject {
private:
QQmlQPointer<QObject> qObj;
+ QQmlPropertyCache *_propertyCache;
+
+public:
+ int index;
};
struct QMetaObjectWrapper : FunctionObject {
@@ -108,14 +127,17 @@ struct QMetaObjectWrapper : FunctionObject {
QQmlPropertyData *constructors;
int constructorCount;
- QMetaObjectWrapper(const QMetaObject* metaObject);
- ~QMetaObjectWrapper();
+ void init(const QMetaObject* metaObject);
+ void destroy();
void ensureConstructorsCache();
};
struct QmlSignalHandler : Object {
- QmlSignalHandler(QObject *object, int signalIndex);
- ~QmlSignalHandler() { qObj.destroy(); }
+ void init(QObject *object, int signalIndex);
+ void destroy() {
+ qObj.destroy();
+ Object::destroy();
+ }
int signalIndex;
QObject *object() const { return qObj.data(); }
@@ -130,6 +152,7 @@ private:
struct Q_QML_EXPORT QObjectWrapper : public Object
{
V4_OBJECT2(QObjectWrapper, Object)
+ V4_NEEDS_DESTROY
enum RevisionMode { IgnoreRevision, CheckRevision };
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 6d6d446ca2..9e94c58432 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -62,11 +62,11 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets)
WTF::String s(string);
#if ENABLE(YARR_JIT)
- if (!jitCode().isFallBack() && jitCode().has16BitCode())
- return uint(jitCode().execute(s.characters16(), start, s.length(), (int*)matchOffsets).start);
+ if (!jitCode()->isFallBack() && jitCode()->has16BitCode())
+ return uint(jitCode()->execute(s.characters16(), start, s.length(), (int*)matchOffsets).start);
#endif
- return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets);
+ return JSC::Yarr::interpret(byteCode(), s.characters16(), string.length(), start, matchOffsets);
}
Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline)
@@ -90,33 +90,41 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
return result->d();
}
-Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
- : pattern(pattern)
- , ignoreCase(ignoreCase)
- , multiLine(multiline)
+void Heap::RegExp::init(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
{
Base::init();
+ this->pattern = new QString(pattern);
+ this->ignoreCase = ignoreCase;
+ this->multiLine = multiline;
const char* error = 0;
JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error);
if (error)
return;
subPatternCount = yarrPattern.m_numSubpatterns;
- byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator);
+ OwnPtr<JSC::Yarr::BytecodePattern> p = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator);
+ byteCode = p.take();
#if ENABLE(YARR_JIT)
+ jitCode = new JSC::Yarr::YarrCodeBlock;
if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) {
JSC::JSGlobalData dummy(engine->regExpAllocator);
- JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, jitCode);
+ JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, *jitCode);
}
#endif
}
-Heap::RegExp::~RegExp()
+void Heap::RegExp::destroy()
{
if (cache) {
RegExpCacheKey key(this);
cache->remove(key);
}
+#if ENABLE(YARR_JIT)
+ delete jitCode;
+#endif
+ delete byteCode;
+ delete pattern;
+ Base::destroy();
}
void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e)
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index b99d717847..d3e63375a5 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -76,12 +76,13 @@ struct RegExpCacheKey;
namespace Heap {
struct RegExp : Base {
- RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline);
- ~RegExp();
- QString pattern;
- OwnPtr<JSC::Yarr::BytecodePattern> byteCode;
+ void init(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline);
+ void destroy();
+
+ QString *pattern;
+ JSC::Yarr::BytecodePattern *byteCode;
#if ENABLE(YARR_JIT)
- JSC::Yarr::YarrCodeBlock jitCode;
+ JSC::Yarr::YarrCodeBlock *jitCode;
#endif
RegExpCache *cache;
int subPatternCount;
@@ -90,6 +91,7 @@ struct RegExp : Base {
int captureCount() const { return subPatternCount + 1; }
};
+V4_ASSERT_IS_TRIVIAL(RegExp)
}
@@ -99,10 +101,10 @@ struct RegExp : public Managed
Q_MANAGED_TYPE(RegExp)
V4_NEEDS_DESTROY
- QString pattern() const { return d()->pattern; }
- OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return d()->byteCode; }
+ QString pattern() const { return *d()->pattern; }
+ JSC::Yarr::BytecodePattern *byteCode() { return d()->byteCode; }
#if ENABLE(YARR_JIT)
- JSC::Yarr::YarrCodeBlock jitCode() const { return d()->jitCode; }
+ JSC::Yarr::YarrCodeBlock *jitCode() const { return d()->jitCode; }
#endif
RegExpCache *cache() const { return d()->cache; }
int subPatternCount() const { return d()->subPatternCount; }
@@ -111,7 +113,7 @@ struct RegExp : public Managed
static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
- bool isValid() const { return d()->byteCode.get(); }
+ bool isValid() const { return d()->byteCode; }
uint match(const QString& string, int start, uint *matchOffsets);
@@ -142,7 +144,7 @@ struct RegExpCacheKey
};
inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
- : pattern(re->pattern)
+ : pattern(*re->pattern)
, ignoreCase(re->ignoreCase)
, multiLine(re->multiLine)
{}
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 203def0bcf..4022d98c3f 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -69,8 +69,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
-Heap::RegExpObject::RegExpObject()
+void Heap::RegExpObject::init()
{
+ Object::init();
Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false);
@@ -78,9 +79,10 @@ Heap::RegExpObject::RegExpObject()
o->initProperties();
}
-Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global)
- : global(global)
+void Heap::RegExpObject::init(QV4::RegExp *value, bool global)
{
+ Object::init();
+ this->global = global;
this->value = value->d();
Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
@@ -90,8 +92,9 @@ Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global)
// Converts a QRegExp to a JS RegExp.
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
-Heap::RegExpObject::RegExpObject(const QRegExp &re)
+void Heap::RegExpObject::init(const QRegExp &re)
{
+ Object::init();
global = false;
// Convert the pattern to a ECMAScript pattern.
@@ -145,7 +148,7 @@ void RegExpObject::initProperties()
Q_ASSERT(value());
- QString p = value()->pattern;
+ QString p = *value()->pattern;
if (p.isEmpty()) {
p = QStringLiteral("(?:)");
} else {
@@ -180,7 +183,7 @@ Value *RegExpObject::lastIndexProperty()
QRegExp RegExpObject::toQRegExp() const
{
Qt::CaseSensitivity caseSensitivity = value()->ignoreCase ? Qt::CaseInsensitive : Qt::CaseSensitive;
- return QRegExp(value()->pattern, caseSensitivity, QRegExp::RegExp2);
+ return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2);
}
QString RegExpObject::toString() const
@@ -217,9 +220,9 @@ uint RegExpObject::flags() const
DEFINE_OBJECT_VTABLE(RegExpCtor);
-Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("RegExp"))
+void Heap::RegExpCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("RegExp"));
clearLastMatch();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 655e120c16..2c82cfdfd1 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -74,16 +74,16 @@ namespace QV4 {
namespace Heap {
struct RegExpObject : Object {
- RegExpObject();
- RegExpObject(QV4::RegExp *value, bool global);
- RegExpObject(const QRegExp &re);
+ void init();
+ void init(QV4::RegExp *value, bool global);
+ void init(const QRegExp &re);
Pointer<RegExp> value;
bool global;
};
struct RegExpCtor : FunctionObject {
- RegExpCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
Value lastMatch;
Pointer<String> lastInput;
int lastMatchStart;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 5460304e7b..fffa6b8009 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -555,7 +555,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu
if (!pright->stringValue()->d()->length())
return pleft->asReturnedValue();
MemoryManager *mm = engine->memoryManager;
- return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue();
+ return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue();
}
double x = RuntimeHelpers::toNumber(pleft);
double y = RuntimeHelpers::toNumber(pright);
@@ -572,7 +572,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu
if (!right.stringValue()->d()->length())
return left.asReturnedValue();
MemoryManager *mm = engine->memoryManager;
- return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d(), true))->asReturnedValue();
+ return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d()))->asReturnedValue();
}
Scope scope(engine);
@@ -590,7 +590,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu
if (!pright->stringValue()->d()->length())
return pleft->asReturnedValue();
MemoryManager *mm = engine->memoryManager;
- return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue();
+ return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue();
}
void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
@@ -1462,7 +1462,7 @@ ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine,
ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
- return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, captureRequired);
}
ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1480,7 +1480,7 @@ ReturnedValue Runtime::method_getQmlIdObject(ExecutionEngine *engine, const Valu
{
Scope scope(engine);
const QmlContext &qmlContext = static_cast<const QmlContext &>(c);
- QQmlContextData *context = qmlContext.d()->qml->context;
+ QQmlContextData *context = *qmlContext.d()->qml->context;
if (!context || index >= (uint)context->idValueCount)
return Encode::undefined();
@@ -1500,7 +1500,7 @@ void Runtime::method_setQmlScopeObjectProperty(ExecutionEngine *engine, const Va
void Runtime::method_setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
{
const QmlContext &c = static_cast<const QmlContext &>(context);
- return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value);
+ return QV4::QObjectWrapper::setProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, value);
}
void Runtime::method_setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 44d171e087..5022d7c3bc 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -324,7 +324,7 @@ struct ScopedCallData {
{
int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value);
ptr = reinterpret_cast<CallData *>(scope.alloc(size));
- ptr->tag = QV4::Value::Integer_Type;
+ ptr->tag = QV4::Value::Integer_Type_Internal;
ptr->argc = argc;
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index b40307d2f0..552171256f 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -65,7 +65,7 @@ namespace QV4 {
namespace Heap {
struct QmlBindingWrapper : FunctionObject {
- QmlBindingWrapper(QV4::QmlContext *scope, Function *f);
+ void init(QV4::QmlContext *scope, Function *f);
};
}
@@ -84,9 +84,10 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
+void Heap::QmlBindingWrapper::init(QV4::QmlContext *scope, Function *f)
{
+ Heap::FunctionObject::init(scope, scope->d()->engine->id_eval(), /*createProto = */ false);
+
Q_ASSERT(scope->inUse());
function = f;
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 59086c245c..3eb7772db7 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -216,11 +216,15 @@ namespace Heap {
template <typename Container>
struct QQmlSequence : Object {
- QQmlSequence(const Container &container);
- QQmlSequence(QObject *object, int propertyIndex);
- ~QQmlSequence() { object.destroy(); }
+ void init(const Container &container);
+ void init(QObject *object, int propertyIndex);
+ void destroy() {
+ delete container;
+ object.destroy();
+ Object::destroy();
+ }
- mutable Container container;
+ mutable Container *container;
QQmlQPointer<QObject> object;
int propertyIndex;
bool isReference;
@@ -260,10 +264,10 @@ public:
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- if (signedIdx < d()->container.count()) {
+ if (signedIdx < d()->container->count()) {
if (hasProperty)
*hasProperty = true;
- return convertElementToValue(engine(), d()->container.at(signedIdx));
+ return convertElementToValue(engine(), d()->container->at(signedIdx));
}
if (hasProperty)
*hasProperty = false;
@@ -289,22 +293,22 @@ public:
qint32 signedIdx = static_cast<qint32>(index);
- int count = d()->container.count();
+ int count = d()->container->count();
typename Container::value_type element = convertValueToElement<typename Container::value_type>(value);
if (signedIdx == count) {
- d()->container.append(element);
+ d()->container->append(element);
} else if (signedIdx < count) {
- d()->container[signedIdx] = element;
+ (*d()->container)[signedIdx] = element;
} else {
/* according to ECMA262r3 we need to insert */
/* the value at the given index, increasing length to index+1. */
- d()->container.reserve(signedIdx + 1);
+ d()->container->reserve(signedIdx + 1);
while (signedIdx > count++) {
- d()->container.append(typename Container::value_type());
+ d()->container->append(typename Container::value_type());
}
- d()->container.append(element);
+ d()->container->append(element);
}
if (d()->isReference)
@@ -324,7 +328,7 @@ public:
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
+ return (signedIdx < d()->container->count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
@@ -340,11 +344,11 @@ public:
loadReference();
}
- if (it->arrayIndex < static_cast<uint>(d()->container.count())) {
+ if (it->arrayIndex < static_cast<uint>(d()->container->count())) {
*index = it->arrayIndex;
++it->arrayIndex;
*attrs = QV4::Attr_Data;
- p->value = convertElementToValue(engine(), d()->container.at(*index));
+ p->value = convertElementToValue(engine(), d()->container->at(*index));
return;
}
QV4::Object::advanceIterator(this, it, name, index, p, attrs);
@@ -362,12 +366,12 @@ public:
}
qint32 signedIdx = static_cast<qint32>(index);
- if (signedIdx >= d()->container.count())
+ if (signedIdx >= d()->container->count())
return false;
/* according to ECMA262r3 it should be Undefined, */
/* but we cannot, so we insert a default-value instead. */
- d()->container.replace(signedIdx, typename Container::value_type());
+ d()->container->replace(signedIdx, typename Container::value_type());
if (d()->isReference)
storeReference();
@@ -432,10 +436,10 @@ public:
QV4::Scope scope(ctx);
if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) {
CompareFunctor cf(ctx, ctx->args()[0]);
- std::sort(d()->container.begin(), d()->container.end(), cf);
+ std::sort(d()->container->begin(), d()->container->end(), cf);
} else {
DefaultCompareFunctor cf;
- std::sort(d()->container.begin(), d()->container.end(), cf);
+ std::sort(d()->container->begin(), d()->container->end(), cf);
}
if (d()->isReference)
@@ -454,7 +458,7 @@ public:
return QV4::Encode(0);
This->loadReference();
}
- return QV4::Encode(This->d()->container.count());
+ return QV4::Encode(This->d()->container->count());
}
static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx)
@@ -478,23 +482,23 @@ public:
}
/* Determine whether we need to modify the sequence */
qint32 newCount = static_cast<qint32>(newLength);
- qint32 count = This->d()->container.count();
+ qint32 count = This->d()->container->count();
if (newCount == count) {
return QV4::Encode::undefined();
} else if (newCount > count) {
/* according to ECMA262r3 we need to insert */
/* undefined values increasing length to newLength. */
/* We cannot, so we insert default-values instead. */
- This->d()->container.reserve(newCount);
+ This->d()->container->reserve(newCount);
while (newCount > count++) {
- This->d()->container.append(typename Container::value_type());
+ This->d()->container->append(typename Container::value_type());
}
} else {
/* according to ECMA262r3 we need to remove */
/* elements until the sequence is the required length. */
while (newCount < count) {
count--;
- This->d()->container.removeAt(count);
+ This->d()->container->removeAt(count);
}
}
/* write back if required. */
@@ -506,7 +510,7 @@ public:
}
QVariant toVariant() const
- { return QVariant::fromValue<Container>(d()->container); }
+ { return QVariant::fromValue<Container>(*d()->container); }
static QVariant toVariant(QV4::ArrayObject *array)
{
@@ -523,7 +527,7 @@ public:
{
Q_ASSERT(d()->object);
Q_ASSERT(d()->isReference);
- void *a[] = { &d()->container, 0 };
+ void *a[] = { d()->container, 0 };
QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a);
}
@@ -533,7 +537,7 @@ public:
Q_ASSERT(d()->isReference);
int status = -1;
QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding;
- void *a[] = { &d()->container, 0, &status, &flags };
+ void *a[] = { d()->container, 0, &status, &flags };
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
@@ -554,11 +558,12 @@ public:
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(const Container &container)
- : container(container)
- , propertyIndex(-1)
- , isReference(false)
+void Heap::QQmlSequence<Container>::init(const Container &container)
{
+ Object::init();
+ this->container = new Container(container);
+ propertyIndex = -1;
+ isReference = false;
object.init();
QV4::Scope scope(internalClass->engine);
@@ -568,10 +573,12 @@ Heap::QQmlSequence<Container>::QQmlSequence(const Container &container)
}
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex)
- : propertyIndex(propertyIndex)
- , isReference(true)
+void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex)
{
+ Object::init();
+ this->container = new Container;
+ this->propertyIndex = propertyIndex;
+ isReference = true;
this->object.init(object);
QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
@@ -594,29 +601,21 @@ typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList;
template<>
DEFINE_OBJECT_VTABLE(QQmlBoolVectorList);
typedef QQmlSequence<QStringList> QQmlQStringList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlQStringList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQStringList);
typedef QQmlSequence<QList<QString> > QQmlStringList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlStringList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringList);
typedef QQmlSequence<QList<int> > QQmlIntList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlIntList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntList);
typedef QQmlSequence<QList<QUrl> > QQmlUrlList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlUrlList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlList);
typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlQModelIndexList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList);
typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlQItemSelectionRangeList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQItemSelectionRangeList);
typedef QQmlSequence<QList<bool> > QQmlBoolList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlBoolList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolList);
typedef QQmlSequence<QList<qreal> > QQmlRealList;
-template<>
-DEFINE_OBJECT_VTABLE(QQmlRealList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealList);
}
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 8bc867e2cd..3365ffe637 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -74,10 +74,10 @@ bool String::isEqualTo(Managed *t, Managed *o)
}
-Heap::String::String(MemoryManager *mm, const QString &t)
- : mm(mm)
+void Heap::String::init(MemoryManager *mm, const QString &t)
{
Base::init();
+ this->mm = mm;
subtype = String::StringType_Unknown;
@@ -89,10 +89,10 @@ Heap::String::String(MemoryManager *mm, const QString &t)
len = text->size;
}
-Heap::String::String(MemoryManager *mm, String *l, String *r, bool) // TODO: remove the dummy bool when String is trivial
- : mm(mm)
+void Heap::String::init(MemoryManager *mm, String *l, String *r)
{
Base::init();
+ this->mm = mm;
subtype = String::StringType_Unknown;
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index f347ea8897..23ec3349b9 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -71,11 +71,12 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
};
#ifndef V4_BOOTSTRAP
- String(MemoryManager *mm, const QString &text);
- String(MemoryManager *mm, String *l, String *n, bool dummy);
- ~String() {
+ void init(MemoryManager *mm, const QString &text);
+ void init(MemoryManager *mm, String *l, String *n);
+ void destroy() {
if (!largestSubLength && !text->ref.deref())
QStringData::deallocate(text);
+ Base::destroy();
}
void simplifyString() const;
int length() const {
@@ -133,6 +134,7 @@ private:
static void append(const String *data, QChar *ch);
#endif
};
+V4_ASSERT_IS_TRIVIAL(String)
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 1989f747e9..829ada0c1a 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -73,15 +73,17 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(StringObject);
-Heap::StringObject::StringObject()
+void Heap::StringObject::init()
{
+ Object::init();
Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
string = internalClass->engine->id_empty()->d();
*propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
}
-Heap::StringObject::StringObject(const QV4::String *str)
+void Heap::StringObject::init(const QV4::String *str)
{
+ Object::init();
string = str->d();
*propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
}
@@ -152,9 +154,9 @@ void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
DEFINE_OBJECT_VTABLE(StringCtor);
-Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, QStringLiteral("String"))
+void Heap::StringCtor::init(QV4::ExecutionContext *scope)
{
+ Heap::FunctionObject::init(scope, QStringLiteral("String"));
}
void StringCtor::construct(const Managed *m, Scope &scope, CallData *callData)
@@ -715,7 +717,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
Scoped<RegExpObject> re(scope, separatorValue);
if (re) {
- if (re->value()->pattern.isEmpty()) {
+ if (re->value()->pattern->isEmpty()) {
re = (RegExpObject *)0;
separatorValue = ctx->d()->engine->newString();
}
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 54425b0909..b9f9d44fe8 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -65,8 +65,8 @@ struct StringObject : Object {
LengthPropertyIndex = 0
};
- StringObject();
- StringObject(const QV4::String *string);
+ void init();
+ void init(const QV4::String *string);
String *string;
Heap::String *getIndex(uint index) const;
@@ -74,7 +74,7 @@ struct StringObject : Object {
};
struct StringCtor : FunctionObject {
- StringCtor(QV4::ExecutionContext *scope);
+ void init(QV4::ExecutionContext *scope);
};
}
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index ae5ebcad1b..009c573bf8 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -202,10 +202,10 @@ const TypedArrayOperations operations[Heap::TypedArray::NTypes] = {
};
-Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t)
- : Heap::FunctionObject(scope, QLatin1String(operations[t].name))
- , type(t)
+void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t)
{
+ Heap::FunctionObject::init(scope, QLatin1String(operations[t].name));
+ type = t;
}
void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callData)
@@ -363,10 +363,11 @@ void TypedArrayCtor::call(const Managed *that, Scope &scope, CallData *callData)
construct(that, scope, callData);
}
-Heap::TypedArray::TypedArray(Type t)
- : type(operations + t),
- arrayType(t)
+void Heap::TypedArray::init(Type t)
{
+ Object::init();
+ type = operations + t;
+ arrayType = t;
}
Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index d96027b96a..0112d2e4a1 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -86,7 +86,7 @@ struct TypedArray : Object {
NTypes
};
- TypedArray(Type t);
+ void init(Type t);
const TypedArrayOperations *type;
Pointer<ArrayBuffer> buffer;
@@ -96,13 +96,13 @@ struct TypedArray : Object {
};
struct TypedArrayCtor : FunctionObject {
- TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t);
+ void init(QV4::ExecutionContext *scope, TypedArray::Type t);
TypedArray::Type type;
};
struct TypedArrayPrototype : Object {
- inline TypedArrayPrototype(TypedArray::Type t);
+ inline void init(TypedArray::Type t);
TypedArray::Type type;
};
@@ -160,10 +160,11 @@ struct TypedArrayPrototype : Object
static ReturnedValue method_subarray(CallContext *ctx);
};
-inline
-Heap::TypedArrayPrototype::TypedArrayPrototype(TypedArray::Type t)
- : type(t)
+inline void
+Heap::TypedArrayPrototype::init(TypedArray::Type t)
{
+ Object::init();
+ type = t;
}
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 78cd4de9fb..4428c48d80 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -76,23 +76,85 @@ 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.
+
+ Specific bit-sequences:
+ 0 = always 0
+ 1 = always 1
+ x = stored value
+ a,b,c,d = specific bit values, see notes
+
+ 64bit:
+
+ 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 00000011 10000000 00000000 00000000 00000000 00000000 00000000 | Null
+ 00000000 00000011 01000000 00000000 00000000 00000000 00000000 0000000x | Bool
+ 00000000 00000011 00100000 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
+
+ 32bit:
+
+ 32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210 |
+ 66665555 55555544 44444444 33333333 33222222 22221111 11111100 00000000 | JS Value
+ ------------------------------------------------------------------------+--------------
+ 01111111 11111100 00000000 00000000 00000000 00000000 00000000 00000000 | Undefined
+ 01111111 11111100 00000000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Managed (heap pointer)
+ a1111111 1111bc00 00000000 00000000 00000000 00000000 00000000 00000000 | NaN/Inf
+ xddddddd ddddddxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | double
+ 01111111 11111110 00000000 00000000 00000000 00000000 00000000 00000000 | empty (non-sparse array hole)
+ 01111111 11111111 10000000 00000000 00000000 00000000 00000000 00000000 | Null
+ 01111111 11111111 01000000 00000000 00000000 00000000 00000000 0000000x | Bool
+ 01111111 11111111 00100000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Int
+
+ Notes:
+ - the upper 32 bits are the tag, the lower 32 bits the value
+ - Undefined has a nullptr in the value, Managed has a non-nullptr stored in the value
+ - a: sign bit, always 0 for NaN
+ - b,c: 00=inf, 01 = sNaN, 10 = qNaN, 11 = boxed value
+ - d: stored double value, as long as not *all* of them are 1, because that's a boxed value
+ (see above)
+ - empty, Null, Bool, and Int have bit 63 set to 0, bits 62-50 set to 1 (same as undefined
+ and managed), and bit 49 set to 1 (where undefined and managed have it set to 0)
+ - Null, Bool, and Int have bit 48 set, indicating integer-convertible
*/
quint64 _val;
@@ -140,7 +202,7 @@ public:
{
quint32 v;
memcpy(&v, &b, 4);
- setTagValue(Managed_Type, v);
+ setTagValue(Managed_Type_Internal, v);
}
#endif
@@ -156,12 +218,43 @@ 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));
+ }
+
+ Q_ALWAYS_INLINE void setEmpty(quint32 i)
+ {
+ setTagValue(Empty_Type_Internal, i);
+ }
+
+ Q_ALWAYS_INLINE quint32 emptyValue()
+ {
+ Q_ASSERT(isEmpty());
+ return quint32(value());
+ }
+
+ 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
@@ -169,101 +262,64 @@ 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 49
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-15,
+ IsIntegerConvertible_Shift = 64-16,
+ Tag_Shift = 32,
+ IsDoubleTag_Shift = IsDouble_Shift - Tag_Shift,
+ Managed_Type_Internal = 0
};
-
-
+#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 48
+ Null_Type_Internal = ConvertibleToInt | 0x08000u,
+ Boolean_Type_Internal = ConvertibleToInt | 0x04000u,
+ Integer_Type_Internal = ConvertibleToInt | 0x02000u
};
-#endif
-
- inline unsigned type() const {
- return tag() & Type_Mask;
- }
// 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 isUndefined() const { return _val == 0; }
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 (_val >> IsIntegerConvertible_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 isUndefined() const { return tag() == Managed_Type_Internal && value() == 0; }
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;
@@ -428,7 +484,7 @@ public:
template<typename T>
Value &operator=(const Scoped<T> &t);
};
-Q_STATIC_ASSERT(std::is_trivial<Value>::value);
+V4_ASSERT_IS_TRIVIAL(Value)
inline bool Value::isString() const
{
@@ -491,6 +547,7 @@ ReturnedValue Heap::Base::asReturnedValue() const
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
inline static Primitive emptyValue();
+ inline static Primitive emptyValue(uint v);
static inline Primitive fromBoolean(bool b);
static inline Primitive fromInt32(int i);
inline static Primitive undefinedValue();
@@ -509,14 +566,21 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value
inline Primitive Primitive::undefinedValue()
{
Primitive v;
- v.setTagValue(Undefined_Type, 0);
+ v.setM(Q_NULLPTR);
return v;
}
inline Primitive Primitive::emptyValue()
{
Primitive v;
- v.setTagValue(Value::Empty_Type, 0);
+ v.setEmpty(0);
+ return v;
+}
+
+inline Primitive Primitive::emptyValue(uint e)
+{
+ Primitive v;
+ v.setEmpty(e);
return v;
}
@@ -544,7 +608,6 @@ inline Primitive Primitive::fromDouble(double d)
inline Primitive Primitive::fromInt32(int i)
{
Primitive v;
- v.setTagValue(Integer_Type_Internal, 0);
v.setInt_32(i);
return v;
}
@@ -562,31 +625,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;
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 39b41dd0d8..455a7ccb65 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -50,20 +50,23 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
-Heap::VariantObject::VariantObject()
+void Heap::VariantObject::init()
{
+ Object::init();
+ scarceData = new ExecutionEngine::ScarceResourceData;
}
-Heap::VariantObject::VariantObject(const QVariant &value)
+void Heap::VariantObject::init(const QVariant &value)
{
- data = value;
+ Object::init();
+ scarceData = new ExecutionEngine::ScarceResourceData(value);
if (isScarce())
- internalClass->engine->scarceResources.insert(this);
+ removeVmePropertyReference();
}
bool VariantObject::Data::isScarce() const
{
- QVariant::Type t = data.type();
+ QVariant::Type t = data().type();
return t == QVariant::Pixmap || t == QVariant::Image;
}
@@ -73,10 +76,10 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other)
QV4::VariantObject *lv = static_cast<QV4::VariantObject *>(m);
if (QV4::VariantObject *rv = other->as<QV4::VariantObject>())
- return lv->d()->data == rv->d()->data;
+ return lv->d()->data() == rv->d()->data();
if (QV4::QQmlValueTypeWrapper *v = other->as<QQmlValueTypeWrapper>())
- return v->isEqual(lv->d()->data);
+ return v->isEqual(lv->d()->data());
return false;
}
@@ -87,7 +90,7 @@ void VariantObject::addVmePropertyReference()
// remove from the ep->scarceResources list
// since it is now no longer eligible to be
// released automatically by the engine.
- d()->node.remove();
+ d()->addVmePropertyReference();
}
}
@@ -97,7 +100,7 @@ void VariantObject::removeVmePropertyReference()
// and add to the ep->scarceResources list
// since it is now eligible to be released
// automatically by the engine.
- internalClass()->engine->scarceResources.insert(d());
+ d()->removeVmePropertyReference();
}
}
@@ -115,7 +118,7 @@ QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
Scope scope(ctx);
Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
if (o && o->d()->isScarce())
- o->d()->node.remove();
+ o->d()->addVmePropertyReference();
return Encode::undefined();
}
@@ -125,8 +128,8 @@ QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx)
Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
if (o) {
if (o->d()->isScarce())
- o->d()->node.remove();
- o->d()->data = QVariant();
+ o->d()->addVmePropertyReference();
+ o->d()->data() = QVariant();
}
return Encode::undefined();
}
@@ -137,10 +140,10 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
if (!o)
return Encode::undefined();
- QString result = o->d()->data.toString();
- if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String)) {
+ QString result = o->d()->data().toString();
+ if (result.isEmpty() && !o->d()->data().canConvert(QVariant::String)) {
result = QLatin1String("QVariant(")
- + QLatin1String(o->d()->data.typeName())
+ + QLatin1String(o->d()->data().typeName())
+ QLatin1Char(')');
}
return Encode(ctx->d()->engine->newString(result));
@@ -151,7 +154,7 @@ QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx)
Scope scope(ctx);
Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>());
if (o) {
- QVariant v = o->d()->data;
+ QVariant v = o->d()->data();
switch (v.type()) {
case QVariant::Invalid:
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index e50706ef94..9a04069c12 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -64,16 +64,28 @@ namespace QV4 {
namespace Heap {
-struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
+struct VariantObject : Object
{
- VariantObject();
- VariantObject(const QVariant &value);
- ~VariantObject() {
+ void init();
+ void init(const QVariant &value);
+ void destroy() {
+ Q_ASSERT(scarceData);
if (isScarce())
- node.remove();
+ addVmePropertyReference();
+ delete scarceData;
+ Object::destroy();
}
bool isScarce() const;
int vmePropertyReferenceCount;
+
+ const QVariant &data() const { return scarceData->data; }
+ QVariant &data() { return scarceData->data; }
+
+ void addVmePropertyReference() { scarceData->node.remove(); }
+ void removeVmePropertyReference() { internalClass->engine->scarceResources.insert(scarceData); }
+
+private:
+ ExecutionEngine::ScarceResourceData *scarceData;
};
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 9d18713253..0f7f6b1f75 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -571,7 +571,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
#endif // DO_TRACE_INSTR
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, engine->runtime.callValue(engine, VALUE(instr.dest), callData));
@@ -581,7 +581,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.callProperty(engine, instr.name, callData));
@@ -590,7 +590,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallPropertyLookup)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.callPropertyLookup(engine, instr.lookupIndex, callData));
@@ -600,7 +600,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.callQmlScopeObjectProperty(engine, instr.index, callData));
@@ -610,7 +610,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.callQmlContextObjectProperty(engine, instr.index, callData));
@@ -619,7 +619,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.callElement(engine, VALUE(instr.index), callData));
@@ -628,7 +628,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallActivationProperty)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, engine->runtime.callActivationProperty(engine, instr.name, callData));
@@ -637,7 +637,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallGlobalLookup)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData));
@@ -743,7 +743,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CreateValue)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, engine->runtime.constructValue(engine, VALUE(instr.func), callData));
@@ -752,7 +752,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CreateProperty)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.constructProperty(engine, instr.name, callData));
@@ -761,7 +761,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
STOREVALUE(instr.result, engine->runtime.constructPropertyLookup(engine, instr.index, callData));
@@ -770,7 +770,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CreateActivationProperty)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, engine->runtime.constructActivationProperty(engine, instr.name, callData));
@@ -779,7 +779,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = QV4::Value::Integer_Type;
+ callData->tag = QV4::Value::Integer_Type_Internal;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
STOREVALUE(instr.result, engine->runtime.constructGlobalLookup(engine, instr.index, callData));
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index cd8d335f1c..f8893509d9 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -51,9 +51,12 @@
// We mean it.
//
+#include <private/qv4global_p.h>
#include <private/qv4runtime_p.h>
#include <private/qv4instr_moth_p.h>
+QT_REQUIRE_CONFIG(qml_interpreter);
+
QT_BEGIN_NAMESPACE
namespace QV4 {
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index d15d14e463..5a3797f397 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -58,6 +58,12 @@
// parent's init all up the inheritance chain), define QML_CHECK_INIT_DESTROY_CALLS below.
#undef QML_CHECK_INIT_DESTROY_CALLS
+#if defined(_MSC_VER) && (_MSC_VER < 1900) // broken compilers:
+# define V4_ASSERT_IS_TRIVIAL(x)
+#else // working compilers:
+# define V4_ASSERT_IS_TRIVIAL(x) Q_STATIC_ASSERT(std::is_trivial< x >::value);
+#endif
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -82,6 +88,8 @@ struct VTable
namespace Heap {
struct Q_QML_EXPORT Base {
+ void *operator new(size_t) = delete;
+
quintptr mm_data; // vtable and markbit
inline ReturnedValue asReturnedValue() const;
@@ -125,16 +133,44 @@ struct Q_QML_EXPORT Base {
void *operator new(size_t, Heap::Base *m) { return m; }
void operator delete(void *, Heap::Base *) {}
- void init() { setInitialized(); }
+ void init() { _setInitialized(); }
+ void destroy() { _setDestroyed(); }
#ifdef QML_CHECK_INIT_DESTROY_CALLS
- bool _isInitialized;
- void _checkIsInitialized() { Q_ASSERT(_isInitialized); }
- void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; }
+ enum { Uninitialized = 0, Initialized, Destroyed } _livenessStatus;
+ void _checkIsInitialized() {
+ if (_livenessStatus == Uninitialized)
+ fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n",
+ vtable()->className);
+ else if (_livenessStatus == Destroyed)
+ fprintf(stderr, "ERROR: use of object '%s' after call to destroy() !!\n",
+ vtable()->className);
+ Q_ASSERT(_livenessStatus = Initialized);
+ }
+ void _checkIsDestroyed() {
+ if (_livenessStatus == Initialized)
+ fprintf(stderr, "ERROR: object '%s' was never destroyed completely !!\n",
+ vtable()->className);
+ Q_ASSERT(_livenessStatus == Destroyed);
+ }
+ void _setInitialized() { Q_ASSERT(_livenessStatus == Uninitialized); _livenessStatus = Initialized; }
+ void _setDestroyed() {
+ if (_livenessStatus == Uninitialized)
+ fprintf(stderr, "ERROR: attempting to destroy an uninitialized object '%s' !!\n",
+ vtable()->className);
+ else if (_livenessStatus == Destroyed)
+ fprintf(stderr, "ERROR: attempting to destroy repeatedly object '%s' !!\n",
+ vtable()->className);
+ Q_ASSERT(_livenessStatus == Initialized);
+ _livenessStatus = Destroyed;
+ }
#else
Q_ALWAYS_INLINE void _checkIsInitialized() {}
- Q_ALWAYS_INLINE void setInitialized() {}
+ Q_ALWAYS_INLINE void _checkIsDestroyed() {}
+ Q_ALWAYS_INLINE void _setInitialized() {}
+ Q_ALWAYS_INLINE void _setDestroyed() {}
#endif
};
+V4_ASSERT_IS_TRIVIAL(Base)
template <typename T>
struct Pointer {
@@ -148,7 +184,7 @@ struct Pointer {
T *ptr;
};
-Q_STATIC_ASSERT(std::is_trivial<Pointer<void>>::value);
+V4_ASSERT_IS_TRIVIAL(Pointer<void>)
}
@@ -204,7 +240,7 @@ private:
QtSharedPointer::ExternalRefCountData *d;
QObject *qObject;
};
-Q_STATIC_ASSERT(std::is_trivial<QQmlQPointer<QObject>>::value);
+V4_ASSERT_IS_TRIVIAL(QQmlQPointer<QObject>)
#endif
}
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 3d25bd1639..6ef2380561 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -46,7 +46,7 @@
#include "PageAllocation.h"
#include "StdLibExtras.h"
-#include <QTime>
+#include <QElapsedTimer>
#include <QMap>
#include <QScopedValueRollback>
@@ -229,10 +229,12 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
*unmanagedHeapSize -= heapBytes;
}
- if (m->vtable()->destroy)
+ if (m->vtable()->destroy) {
m->vtable()->destroy(m);
+ m->_checkIsDestroyed();
+ }
- memset(m, 0, header->itemSize);
+ memset(m, 0, sizeof(Heap::Base));
#ifdef V4_USE_VALGRIND
VALGRIND_DISABLE_ERROR_REPORTING;
VALGRIND_MEMPOOL_FREE(engine->memoryManager, m);
@@ -482,7 +484,7 @@ void MemoryManager::sweep(bool lastSweep)
remainingWeakQObjectWrappers.reserve(pendingCount);
for (int i = 0; i < pendingCount; ++i) {
Value *v = m_pendingFreedObjectWrapperValue.at(i);
- if (v->tag() == Value::Undefined_Type)
+ if (v->isUndefined() || v->isEmpty())
PersistentValueStorage::free(v);
else
remainingWeakQObjectWrappers.append(v);
@@ -594,18 +596,17 @@ void MemoryManager::runGC()
} else {
const size_t totalMem = getAllocatedMem();
- QTime t;
+ QElapsedTimer t;
t.start();
mark();
- int markTime = t.elapsed();
- t.restart();
+ qint64 markTime = t.restart();
const size_t usedBefore = getUsedMem();
const size_t largeItemsBefore = getLargeItemsMem();
size_t chunksBefore = m_d->heapChunks.size();
sweep();
const size_t usedAfter = getUsedMem();
const size_t largeItemsAfter = getLargeItemsMem();
- int sweepTime = t.elapsed();
+ qint64 sweepTime = t.elapsed();
qDebug() << "========== GC ==========";
qDebug() << "Marked object in" << markTime << "ms.";
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 6db5b54760..dfa0d85dff 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -108,8 +108,10 @@ public:
template<typename ManagedType>
inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0)
{
+ V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data)
size = align(size);
Heap::Base *o = allocData(size, unmanagedSize);
+ memset(o, 0, size);
o->setVtable(ManagedType::staticVTable());
return static_cast<typename ManagedType::Data *>(o);
}
@@ -144,7 +146,7 @@ public:
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
- (void)new (t->d()) typename ManagedType::Data(this, arg1);
+ t->d_unchecked()->init(this, arg1);
return t->d();
}
@@ -153,7 +155,7 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- (void)new (t->d()) typename ObjectType::Data();
+ t->d_unchecked()->init();
return t->d();
}
@@ -162,8 +164,8 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- t->d()->prototype = prototype->d();
- (void)new (t->d()) typename ObjectType::Data();
+ t->d_unchecked()->prototype = prototype->d();
+ t->d_unchecked()->init();
return t->d();
}
@@ -172,8 +174,8 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- t->d()->prototype = prototype->d();
- (void)new (t->d()) typename ObjectType::Data(arg1);
+ t->d_unchecked()->prototype = prototype->d();
+ t->d_unchecked()->init(arg1);
return t->d();
}
@@ -182,8 +184,8 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- t->d()->prototype = prototype->d();
- (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ t->d_unchecked()->prototype = prototype->d();
+ t->d_unchecked()->init(arg1, arg2);
return t->d();
}
@@ -192,8 +194,8 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- t->d()->prototype = prototype->d();
- (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ t->d_unchecked()->prototype = prototype->d();
+ t->d_unchecked()->init(arg1, arg2, arg3);
return t->d();
}
@@ -202,8 +204,8 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
- t->d()->prototype = prototype->d();
- (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ t->d_unchecked()->prototype = prototype->d();
+ t->d_unchecked()->init(arg1, arg2, arg3, arg4);
return t->d();
}
@@ -212,7 +214,7 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- (void)new (t->d()) typename ObjectType::Data();
+ t->d_unchecked()->init();
return t->d();
}
@@ -221,7 +223,7 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- (void)new (t->d()) typename ObjectType::Data(arg1);
+ t->d_unchecked()->init(arg1);
return t->d();
}
@@ -230,7 +232,7 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ t->d_unchecked()->init(arg1, arg2);
return t->d();
}
@@ -239,7 +241,7 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ t->d_unchecked()->init(arg1, arg2, arg3);
return t->d();
}
@@ -248,7 +250,7 @@ public:
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ t->d_unchecked()->init(arg1, arg2, arg3, arg4);
return t->d();
}
@@ -258,7 +260,7 @@ public:
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data();
+ t->d_unchecked()->init();
return t->d();
}
@@ -267,7 +269,7 @@ public:
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data(arg1);
+ t->d_unchecked()->init(arg1);
return t->d();
}
@@ -294,7 +296,7 @@ public:
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
+ t->d_unchecked()->init(arg1, arg2, arg3, arg4);
return t->d();
}
@@ -303,7 +305,7 @@ public:
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
+ t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5);
return t->d();
}
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index 13e00d8812..826a074701 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -1,11 +1,8 @@
TARGET = QtQml
QT = core-private
-no_network {
- DEFINES += QT_NO_NETWORK
-} else {
+qtConfig(qml-network): \
QT += network
-}
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
@@ -22,11 +19,6 @@ exists("qqml_enable_gcov") {
LIBS_PRIVATE += -lgcov
}
-gcc:!intel_icc:greaterThan(QT_GCC_MAJOR_VERSION, 5) {
- # Our code is bad. Temporary workaround.
- QMAKE_CXXFLAGS += -fno-delete-null-pointer-checks -fno-lifetime-dse
-}
-
# QTBUG-55238, disable new optimizer for MSVC 2015/Update 3.
release:win32-msvc*:equals(QT_CL_MAJOR_VERSION, 19):equals(QT_CL_MINOR_VERSION, 00): \
greaterThan(QT_CL_PATCH_VERSION, 24212):QMAKE_CXXFLAGS += -d2SSAOptimizer-
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index e12472760f..4fe76ddf29 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -600,7 +600,7 @@ protected:
resultMo = resultObject->metaObject();
}
} else if (auto variant = result.as<QV4::VariantObject>()) {
- QVariant value = variant->d()->data;
+ QVariant value = variant->d()->data();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
if (resultMo.isNull())
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index b78028dcf9..6ebcd142fb 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1058,9 +1058,9 @@ namespace QV4 {
namespace Heap {
struct QmlIncubatorObject : Object {
- QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
- ~QmlIncubatorObject() { parent.destroy(); }
- QScopedPointer<QQmlComponentIncubator> incubator;
+ void init(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ inline void destroy();
+ QQmlComponentIncubator *incubator;
QQmlQPointer<QObject> parent;
QV4::Value valuemap;
QV4::Value statusChanged;
@@ -1389,7 +1389,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
r->d()->qmlContext = v4->qmlContext();
r->d()->parent = parent;
- QQmlIncubator *incubator = r->d()->incubator.data();
+ QQmlIncubator *incubator = r->d()->incubator;
create(*incubator, creationContext());
if (incubator->status() == QQmlIncubator::Null) {
@@ -1484,13 +1484,20 @@ QQmlComponentExtension::~QQmlComponentExtension()
{
}
-QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m)
- : valuemap(QV4::Primitive::undefinedValue())
- , statusChanged(QV4::Primitive::undefinedValue())
+void QV4::Heap::QmlIncubatorObject::init(QQmlIncubator::IncubationMode m)
{
+ Object::init();
+ valuemap = QV4::Primitive::undefinedValue();
+ statusChanged = QV4::Primitive::undefinedValue();
parent.init();
qmlContext = nullptr;
- incubator.reset(new QQmlComponentIncubator(this, m));
+ incubator = new QQmlComponentIncubator(this, m);
+}
+
+void QV4::Heap::QmlIncubatorObject::destroy() {
+ delete incubator;
+ parent.destroy();
+ Object::destroy();
}
void QV4::QmlIncubatorObject::setInitialState(QObject *o)
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 13d708bc17..2418003519 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -61,20 +61,23 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlContextWrapper);
-Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
- : readOnly(true)
- , ownsContext(ownsContext)
- , isNullWrapper(false)
- , context(context)
+void Heap::QmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
{
+ Object::init();
+ readOnly = true;
+ this->ownsContext = ownsContext;
+ isNullWrapper = false;
+ this->context = new QQmlGuardedContextData(context);
this->scopeObject.init(scopeObject);
}
-Heap::QmlContextWrapper::~QmlContextWrapper()
+void Heap::QmlContextWrapper::destroy()
{
- if (context && ownsContext)
- context->destroy();
+ if (*context && ownsContext)
+ (*context)->destroy();
+ delete context;
scopeObject.destroy();
+ Object::destroy();
}
ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *ctxt, QObject *scope)
@@ -120,7 +123,7 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr
if (resource->d()->isNullWrapper)
return Object::get(m, name, hasProperty);
- if (v4->callingQmlContext() != resource->d()->context)
+ if (v4->callingQmlContext() != *resource->d()->context)
return Object::get(m, name, hasProperty);
result = Object::get(m, name, &hasProp);
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 2b8c16f274..126ffecf0d 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -64,13 +64,13 @@ namespace QV4 {
namespace Heap {
struct QmlContextWrapper : Object {
- QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
- ~QmlContextWrapper();
+ void init(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
+ void destroy();
bool readOnly;
bool ownsContext;
bool isNullWrapper;
- QQmlGuardedContextData context;
+ QQmlGuardedContextData *context;
QQmlQPointer<QObject> scopeObject;
};
@@ -89,7 +89,7 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
}
inline QObject *getScopeObject() const { return d()->scopeObject; }
- inline QQmlContextData *getContext() const { return d()->context; }
+ inline QQmlContextData *getContext() const { return *d()->context; }
void setReadOnly(bool b) { d()->readOnly = b; }
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index daa12fae26..c273330a0a 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -70,7 +70,7 @@
#include <QtCore/qthread.h>
#include <private/qthread_p.h>
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
#include "qqmlnetworkaccessmanagerfactory.h"
#include <QNetworkAccessManager>
#include <QtNetwork/qnetworkconfigmanager.h>
@@ -660,7 +660,7 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
activeObjectCreator(0),
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
networkAccessManager(0), networkAccessManagerFactory(0),
#endif
urlInterceptor(0), scarceResourcesRefCount(0), importDatabase(e), typeLoader(e),
@@ -1143,7 +1143,7 @@ void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
}
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
/*!
Sets the \a factory to use for creating QNetworkAccessManager(s).
@@ -1210,7 +1210,7 @@ QNetworkAccessManager *QQmlEngine::networkAccessManager() const
Q_D(const QQmlEngine);
return d->getNetworkAccessManager();
}
-#endif // QT_NO_NETWORK
+#endif // qml_network
/*!
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 3111d1013e..3102a20fac 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -87,7 +87,7 @@ class QQmlExpression;
class QQmlContext;
class QQmlType;
class QUrl;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
class QNetworkAccessManager;
class QQmlNetworkAccessManagerFactory;
#endif
@@ -117,7 +117,7 @@ public:
bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors);
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *);
QQmlNetworkAccessManagerFactory *networkAccessManagerFactory() const;
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 713b03dbf3..916566b6c7 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -162,7 +162,7 @@ public:
void registerFinalizeCallback(QObject *obj, int index);
QQmlObjectCreator *activeObjectCreator;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
QNetworkAccessManager *getNetworkAccessManager() const;
mutable QNetworkAccessManager *networkAccessManager;
diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp
index 4769402855..4e4db086b0 100644
--- a/src/qml/qml/qqmlfile.cpp
+++ b/src/qml/qml/qqmlfile.cpp
@@ -68,7 +68,7 @@ static char assets_string[] = "assets";
class QQmlFilePrivate;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
class QQmlFileNetworkReply : public QObject
{
Q_OBJECT
@@ -117,12 +117,12 @@ public:
Error error;
QString errorString;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QQmlFileNetworkReply *reply;
#endif
};
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
int QQmlFileNetworkReply::finishedIndex = -1;
int QQmlFileNetworkReply::downloadProgressIndex = -1;
int QQmlFileNetworkReply::networkFinishedIndex = -1;
@@ -205,11 +205,11 @@ void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b)
{
emit downloadProgress(a, b);
}
-#endif // QT_NO_NETWORK
+#endif // qml_network
QQmlFilePrivate::QQmlFilePrivate()
: error(None)
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
, reply(0)
#endif
{
@@ -233,7 +233,7 @@ QQmlFile::QQmlFile(QQmlEngine *e, const QString &url)
QQmlFile::~QQmlFile()
{
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
delete d->reply;
#endif
delete d;
@@ -273,7 +273,7 @@ QQmlFile::Status QQmlFile::status() const
{
if (d->url.isEmpty() && d->urlString.isEmpty())
return Null;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
else if (d->reply)
return Loading;
#endif
@@ -333,7 +333,7 @@ void QQmlFile::load(QQmlEngine *engine, const QUrl &url)
d->error = QQmlFilePrivate::NotFound;
}
} else {
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
d->reply = new QQmlFileNetworkReply(engine, d, url);
#else
d->error = QQmlFilePrivate::NotFound;
@@ -364,7 +364,7 @@ void QQmlFile::load(QQmlEngine *engine, const QString &url)
d->error = QQmlFilePrivate::NotFound;
}
} else {
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QUrl qurl(url);
d->url = qurl;
d->urlString = QString();
@@ -388,7 +388,7 @@ void QQmlFile::clear(QObject *)
clear();
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
bool QQmlFile::connectFinished(QObject *object, const char *method)
{
if (!d || !d->reply) {
diff --git a/src/qml/qml/qqmlfile.h b/src/qml/qml/qqmlfile.h
index 3dd683a2cd..aec0981a95 100644
--- a/src/qml/qml/qqmlfile.h
+++ b/src/qml/qml/qqmlfile.h
@@ -80,7 +80,7 @@ public:
void clear();
void clear(QObject *);
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
bool connectFinished(QObject *, const char *);
bool connectFinished(QObject *, int);
bool connectDownloadProgress(QObject *, const char *);
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 425a720867..8aa107dc17 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -52,17 +52,19 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlListWrapper);
-Heap::QmlListWrapper::QmlListWrapper()
+void Heap::QmlListWrapper::init()
{
+ Object::init();
object.init();
QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
}
-Heap::QmlListWrapper::~QmlListWrapper()
+void Heap::QmlListWrapper::destroy()
{
object.destroy();
+ Object::destroy();
}
ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, int propType)
@@ -75,7 +77,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i
Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
r->d()->object = object;
r->d()->propertyType = propType;
- void *args[] = { &r->d()->property, 0 };
+ void *args[] = { &r->d()->property(), 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
return r.asReturnedValue();
}
@@ -86,7 +88,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp
Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
r->d()->object = prop.object;
- r->d()->property = prop;
+ r->d()->property() = prop;
r->d()->propertyType = propType;
return r.asReturnedValue();
}
@@ -96,7 +98,7 @@ QVariant QmlListWrapper::toVariant() const
if (!d()->object)
return QVariant();
- return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property, d()->propertyType, engine()->qmlEngine()));
+ return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property(), d()->propertyType, engine()->qmlEngine()));
}
@@ -107,7 +109,7 @@ ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasPrope
QV4::ExecutionEngine *v4 = w->engine();
if (name->equals(v4->id_length()) && !w->d()->object.isNull()) {
- quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
+ quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
return Primitive::fromUInt32(count).asReturnedValue();
}
@@ -126,11 +128,11 @@ ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *has
const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
- quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
- if (index < count && w->d()->property.at) {
+ quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
+ if (index < count && w->d()->property().at) {
if (hasProperty)
*hasProperty = true;
- return QV4::QObjectWrapper::wrap(v4, w->d()->property.at(&w->d()->property, index));
+ return QV4::QObjectWrapper::wrap(v4, w->d()->property().at(&w->d()->property(), index));
}
if (hasProperty)
@@ -152,12 +154,12 @@ void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name
*index = UINT_MAX;
Q_ASSERT(m->as<QmlListWrapper>());
QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
- quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
+ quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
if (it->arrayIndex < count) {
*index = it->arrayIndex;
++it->arrayIndex;
*attrs = QV4::Attr_Data;
- p->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property.at(&w->d()->property, *index));
+ p->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property().at(&w->d()->property(), *index));
return;
}
return QV4::Object::advanceIterator(m, it, name, index, p, attrs);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 1107b957c9..d01b332159 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -66,11 +66,18 @@ namespace QV4 {
namespace Heap {
struct QmlListWrapper : Object {
- QmlListWrapper();
- ~QmlListWrapper();
+ void init();
+ void destroy();
QQmlQPointer<QObject> object;
- QQmlListProperty<QObject> property;
+
+ QQmlListProperty<QObject> &property() {
+ return *reinterpret_cast<QQmlListProperty<QObject>*>(propertyData);
+ }
+
int propertyType;
+
+private:
+ void *propertyData[sizeof(QQmlListProperty<QObject>)/sizeof(void*)];
};
}
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 76752f509c..6f66475aa5 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -109,16 +109,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct
if (ctx->argc() == 2) {
if (ctx->args()[1].isString()) {
QString format = ctx->args()[1].stringValue()->toQString();
- formattedDt = r->d()->locale.toString(dt, format);
+ formattedDt = r->d()->locale->toString(dt, format);
} else if (ctx->args()[1].isNumber()) {
quint32 intFormat = ctx->args()[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- formattedDt = r->d()->locale.toString(dt, format);
+ formattedDt = r->d()->locale->toString(dt, format);
} else {
V4THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
}
} else {
- formattedDt = r->d()->locale.toString(dt, enumFormat);
+ formattedDt = r->d()->locale->toString(dt, enumFormat);
}
return ctx->d()->engine->newString(formattedDt)->asReturnedValue();
@@ -154,16 +154,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext
if (ctx->argc() == 2) {
if (ctx->args()[1].isString()) {
QString format = ctx->args()[1].stringValue()->toQString();
- formattedTime = r->d()->locale.toString(time, format);
+ formattedTime = r->d()->locale->toString(time, format);
} else if (ctx->args()[1].isNumber()) {
quint32 intFormat = ctx->args()[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- formattedTime = r->d()->locale.toString(time, format);
+ formattedTime = r->d()->locale->toString(time, format);
} else {
V4THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
}
} else {
- formattedTime = r->d()->locale.toString(time, enumFormat);
+ formattedTime = r->d()->locale->toString(time, enumFormat);
}
return ctx->d()->engine->newString(formattedTime)->asReturnedValue();
@@ -199,16 +199,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext
if (ctx->argc() == 2) {
if (ctx->args()[1].isString()) {
QString format = ctx->args()[1].stringValue()->toQString();
- formattedDate = r->d()->locale.toString(date, format);
+ formattedDate = r->d()->locale->toString(date, format);
} else if (ctx->args()[1].isNumber()) {
quint32 intFormat = ctx->args()[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- formattedDate = r->d()->locale.toString(date, format);
+ formattedDate = r->d()->locale->toString(date, format);
} else {
V4THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
}
} else {
- formattedDate = r->d()->locale.toString(date, enumFormat);
+ formattedDate = r->d()->locale->toString(date, enumFormat);
}
return ctx->d()->engine->newString(formattedDate)->asReturnedValue();
@@ -237,16 +237,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext *
if (ctx->argc() == 3) {
if (ctx->args()[2].isString()) {
QString format = ctx->args()[2].stringValue()->toQString();
- dt = r->d()->locale.toDateTime(dateString, format);
+ dt = r->d()->locale->toDateTime(dateString, format);
} else if (ctx->args()[2].isNumber()) {
quint32 intFormat = ctx->args()[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- dt = r->d()->locale.toDateTime(dateString, format);
+ dt = r->d()->locale->toDateTime(dateString, format);
} else {
V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
}
} else {
- dt = r->d()->locale.toDateTime(dateString, enumFormat);
+ dt = r->d()->locale->toDateTime(dateString, enumFormat);
}
return QV4::Encode(engine->newDateObject(dt));
@@ -278,16 +278,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallConte
if (ctx->argc() == 3) {
if (ctx->args()[2].isString()) {
QString format = ctx->args()[2].stringValue()->toQString();
- tm = r->d()->locale.toTime(dateString, format);
+ tm = r->d()->locale->toTime(dateString, format);
} else if (ctx->args()[2].isNumber()) {
quint32 intFormat = ctx->args()[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- tm = r->d()->locale.toTime(dateString, format);
+ tm = r->d()->locale->toTime(dateString, format);
} else {
V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
}
} else {
- tm = r->d()->locale.toTime(dateString, enumFormat);
+ tm = r->d()->locale->toTime(dateString, enumFormat);
}
QDateTime dt;
@@ -323,16 +323,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallConte
if (ctx->argc() == 3) {
if (ctx->args()[2].isString()) {
QString format = ctx->args()[2].stringValue()->toQString();
- dt = r->d()->locale.toDate(dateString, format);
+ dt = r->d()->locale->toDate(dateString, format);
} else if (ctx->args()[2].isNumber()) {
quint32 intFormat = ctx->args()[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- dt = r->d()->locale.toDate(dateString, format);
+ dt = r->d()->locale->toDate(dateString, format);
} else {
V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
}
} else {
- dt = r->d()->locale.toDate(dateString, enumFormat);
+ dt = r->d()->locale->toDate(dateString, enumFormat);
}
return QV4::Encode(engine->newDateObject(QDateTime(dt)));
@@ -393,7 +393,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *
prec = ctx->args()[2].toInt32();
}
- return ctx->d()->engine->newString(r->d()->locale.toString(number, (char)format, prec))->asReturnedValue();
+ return ctx->d()->engine->newString(r->d()->locale->toString(number, (char)format, prec))->asReturnedValue();
}
QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallContext *ctx)
@@ -423,7 +423,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallC
symbol = ctx->args()[1].toQStringNoThrow();
}
- return ctx->d()->engine->newString(r->d()->locale.toCurrencyString(number, symbol))->asReturnedValue();
+ return ctx->d()->engine->newString(r->d()->locale->toCurrencyString(number, symbol))->asReturnedValue();
}
QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext *ctx)
@@ -441,7 +441,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext
V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
GET_LOCALE_DATA_RESOURCE(ctx->args()[0]);
- locale = r->d()->locale;
+ locale = *r->d()->locale;
numberIdx = 1;
}
@@ -813,7 +813,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
QV4::Scope scope(v4);
QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>());
- wrapper->d()->locale = locale;
+ *wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
wrapper->setPrototype(p);
return wrapper.asReturnedValue();
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 652a3ca0d4..275f58db7d 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -143,8 +143,12 @@ namespace QV4 {
namespace Heap {
struct QQmlLocaleData : Object {
- inline QQmlLocaleData() {}
- QLocale locale;
+ inline void init() { locale = new QLocale; }
+ void destroy() {
+ delete locale;
+ Object::destroy();
+ }
+ QLocale *locale;
};
}
@@ -161,7 +165,7 @@ struct QQmlLocaleData : public QV4::Object
ctx->engine()->throwTypeError();
return 0;
}
- return &thisObject->d()->locale;
+ return thisObject->d()->locale;
}
static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx);
diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp
index 88cf14cba0..fd8fb477c7 100644
--- a/src/qml/qml/qqmlloggingcategory.cpp
+++ b/src/qml/qml/qqmlloggingcategory.cpp
@@ -81,7 +81,7 @@
\note This property needs to be set when declaring the LoggingCategory
and cannot be changed later.
- \sa QLoggingCategory::name()
+ \sa QLoggingCategory::categoryName()
*/
QQmlLoggingCategory::QQmlLoggingCategory(QObject *parent)
diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp
index c94db8e168..1680253d73 100644
--- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp
+++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp
@@ -41,7 +41,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
/*!
\class QQmlNetworkAccessManagerFactory
@@ -103,6 +103,6 @@ QQmlNetworkAccessManagerFactory::~QQmlNetworkAccessManagerFactory()
implementation of this method is reentrant.
*/
-#endif //QT_NO_NETWORK
+#endif // qml_network
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h
index ba3561b9f4..57dec1da29 100644
--- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h
+++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
class QNetworkAccessManager;
class Q_QML_EXPORT QQmlNetworkAccessManagerFactory
@@ -56,7 +56,7 @@ public:
};
-#endif //QT_NO_NETWORK
+#endif // qml_network
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 2543fd069c..672b36ea75 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -246,7 +246,7 @@ Creates a new empty QQmlPropertyCache.
QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e)
: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
- _metaObject(0), argumentsCache(0)
+ _metaObject(0), argumentsCache(0), _jsFactoryMethodIndex(-1)
{
Q_ASSERT(engine);
}
@@ -507,6 +507,11 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
const char *name = mci.name();
if (0 == qstrcmp(name, "DefaultProperty")) {
_defaultPropertyName = QString::fromUtf8(mci.value());
+ } else if (0 == qstrcmp(name, "qt_QmlJSWrapperFactoryMethod")) {
+ const char * const factoryMethod = mci.value();
+ _jsFactoryMethodIndex = metaObject->indexOfSlot(factoryMethod);
+ if (_jsFactoryMethodIndex != -1)
+ _jsFactoryMethodIndex -= metaObject->methodOffset();
}
}
}
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index f90945bf57..b820777973 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -431,6 +431,8 @@ public:
void toMetaObjectBuilder(QMetaObjectBuilder &);
+ inline bool callJSFactoryMethod(QObject *object, void **args) const;
+
static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
@@ -505,6 +507,7 @@ private:
QByteArray _dynamicStringData;
QString _defaultPropertyName;
QQmlPropertyCacheMethodArguments *argumentsCache;
+ int _jsFactoryMethodIndex;
QByteArray _checksum;
};
@@ -806,6 +809,17 @@ int QQmlPropertyCache::signalOffset() const
return signalHandlerIndexCacheStart;
}
+bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
+{
+ if (_jsFactoryMethodIndex != -1) {
+ _metaObject->d.static_metacall(object, QMetaObject::InvokeMetaMethod, _jsFactoryMethodIndex, args);
+ return true;
+ }
+ if (_parent)
+ return _parent->callJSFactoryMethod(object, args);
+ return false;
+}
+
QQmlMetaObject::QQmlMetaObject()
{
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index b576366abf..3e599aed6c 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -123,7 +123,7 @@ namespace {
};
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
// This is a lame object that we need to ensure that slots connected to
// QNetworkReply get called in the correct thread (the loader thread).
// As QQmlTypeLoader lives in the main thread, and we can't use
@@ -143,7 +143,7 @@ public slots:
private:
QQmlTypeLoader *l;
};
-#endif // QT_NO_NETWORK
+#endif // qml_network
class QQmlTypeLoaderThread : public QQmlThread
{
@@ -151,10 +151,10 @@ class QQmlTypeLoaderThread : public QQmlThread
public:
QQmlTypeLoaderThread(QQmlTypeLoader *loader);
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *networkAccessManager() const;
QQmlTypeLoaderNetworkReplyProxy *networkReplyProxy() const;
-#endif // QT_NO_NETWORK
+#endif // qml_network
void load(QQmlDataBlob *b);
void loadAsync(QQmlDataBlob *b);
void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
@@ -177,13 +177,13 @@ private:
void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
QQmlTypeLoader *m_loader;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
mutable QNetworkAccessManager *m_networkAccessManager;
mutable QQmlTypeLoaderNetworkReplyProxy *m_networkReplyProxy;
-#endif // QT_NO_NETWORK
+#endif // qml_network
};
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QQmlTypeLoaderNetworkReplyProxy::QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l)
: l(l)
{
@@ -212,7 +212,7 @@ void QQmlTypeLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply)
l->networkReplyProgress(reply, replySize, replySize);
l->networkReplyFinished(reply);
}
-#endif // QT_NO_NETWORK
+#endif // qml_network
/*!
\class QQmlDataBlob
@@ -529,7 +529,7 @@ void QQmlDataBlob::done()
{
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
/*!
Invoked if there is a network error while fetching this blob.
@@ -582,7 +582,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
setError(error);
}
-#endif // QT_NO_NETWORK
+#endif // qml_network
/*!
Called if \a blob, which was previously waited for, has an error.
@@ -782,15 +782,15 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v)
QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader)
: m_loader(loader)
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
, m_networkAccessManager(0), m_networkReplyProxy(0)
-#endif // QT_NO_NETWORK
+#endif // qml_network
{
// Do that after initializing all the members.
startup();
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const
{
Q_ASSERT(isThisThread());
@@ -808,7 +808,7 @@ QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const
Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first
return m_networkReplyProxy;
}
-#endif // QT_NO_NETWORK
+#endif // qml_network
void QQmlTypeLoaderThread::load(QQmlDataBlob *b)
{
@@ -866,12 +866,12 @@ void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
void QQmlTypeLoaderThread::shutdownThread()
{
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
delete m_networkAccessManager;
m_networkAccessManager = 0;
delete m_networkReplyProxy;
m_networkReplyProxy = 0;
-#endif // QT_NO_NETWORK
+#endif // qml_network
}
void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b)
@@ -957,14 +957,14 @@ void QQmlTypeLoader::invalidate()
m_thread = 0;
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
// Need to delete the network replies after
// the loader thread is shutdown as it could be
// getting new replies while we clear them
for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
(*iter)->release();
m_networkReplies.clear();
-#endif // QT_NO_NETWORK
+#endif // qml_network
}
void QQmlTypeLoader::lock()
@@ -1138,7 +1138,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
setData(blob, fileName);
} else {
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url));
QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy();
blob->addref();
@@ -1156,14 +1156,14 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
#ifdef DATABLOB_DEBUG
qWarning("QQmlDataBlob: requested %s", qPrintable(blob->url().toString()));
#endif // DATABLOB_DEBUG
-#endif // QT_NO_NETWORK
+#endif // qml_network
}
}
#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
#define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
{
Q_ASSERT(m_thread->isThisThread());
@@ -1219,7 +1219,7 @@ void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply,
m_thread->callDownloadProgressChanged(blob, blob->m_data.progress());
}
}
-#endif // QT_NO_NETWORK
+#endif // qml_network
/*!
Return the QQmlEngine associated with this loader
@@ -1968,12 +1968,11 @@ void QQmlTypeLoader::trimCache()
for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end; ++iter) {
QQmlTypeData *typeData = iter.value();
- const bool hasError = !typeData->m_compiledData && !typeData->m_errors.isEmpty();
- const bool isNotReferenced = typeData->isComplete() && typeData->m_compiledData
- && typeData->m_compiledData->count() == 1;
- // typeData->m_compiledData may be set early on in the proccess of loading a file, so it's important
- // to check the general loading status of the typeData before making any other decisions.
- if (typeData->count() == 1 && (hasError || isNotReferenced)) {
+ // typeData->m_compiledData may be set early on in the proccess of loading a file, so
+ // it's important to check the general loading status of the typeData before making any
+ // other decisions.
+ if (typeData->count() == 1 && (typeData->isError() || typeData->isComplete())
+ && (!typeData->m_compiledData || typeData->m_compiledData->count() == 1)) {
// There are no live objects of this type
unneededTypes.append(iter);
}
@@ -3106,8 +3105,14 @@ QByteArray QQmlDataBlob::Data::readAll(QString *error, qint64 *sourceTimeStamp)
*error = f.errorString();
return QByteArray();
}
- if (sourceTimeStamp)
- *sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
+ if (sourceTimeStamp) {
+ QDateTime timeStamp = QFileInfo(f).lastModified();
+ // Files from the resource system do not have any time stamps, so fall back to the application
+ // executable.
+ if (!timeStamp.isValid())
+ timeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
+ *sourceTimeStamp = timeStamp.toMSecsSinceEpoch();
+ }
QByteArray data(f.size(), Qt::Uninitialized);
if (f.read(data.data(), data.length()) != data.length()) {
*error = f.errorString();
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 12c55e9179..ad5ab3124e 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -51,9 +51,10 @@
// We mean it.
//
+#include <QtQml/qtqmlglobal.h>
#include <QtCore/qobject.h>
#include <QtCore/qatomic.h>
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
#include <QtNetwork/qnetworkreply.h>
#endif
#include <QtQml/qqmlerror.h>
@@ -154,7 +155,7 @@ protected:
virtual void dataReceived(const Data &) = 0;
virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit*) = 0;
virtual void done();
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
virtual void networkError(QNetworkReply::NetworkError);
#endif
virtual void dependencyError(QQmlDataBlob *);
@@ -320,16 +321,16 @@ public:
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoaderThread;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
friend class QQmlTypeLoaderNetworkReplyProxy;
-#endif // QT_NO_NETWORK
+#endif // qml_network
void shutdownThread();
void loadThread(QQmlDataBlob *);
void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
void loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
void networkReplyFinished(QNetworkReply *);
void networkReplyProgress(QNetworkReply *, qint64, qint64);
@@ -366,7 +367,7 @@ private:
QQmlEngine *m_engine;
QQmlTypeLoaderThread *m_thread;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
NetworkReplies m_networkReplies;
#endif
TypeCache m_typeCache;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 28c2588117..5c3ad6b2a6 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -55,17 +55,19 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
-Heap::QmlTypeWrapper::QmlTypeWrapper()
- : mode(IncludeEnums)
+void Heap::QmlTypeWrapper::init()
{
+ Object::init();
+ mode = IncludeEnums;
object.init();
}
-Heap::QmlTypeWrapper::~QmlTypeWrapper()
+void Heap::QmlTypeWrapper::destroy()
{
if (typeNamespace)
typeNamespace->release();
object.destroy();
+ Object::destroy();
}
bool QmlTypeWrapper::isSingleton() const
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 7c5105b184..3b0ae04cc1 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -71,8 +71,8 @@ struct QmlTypeWrapper : Object {
ExcludeEnums
};
- QmlTypeWrapper();
- ~QmlTypeWrapper();
+ void init();
+ void destroy();
TypeNameMode mode;
QQmlQPointer<QObject> object;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 2625f5af11..43b9e4bd3b 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -63,8 +63,14 @@ namespace Heap {
struct QQmlValueTypeReference : QQmlValueTypeWrapper
{
- QQmlValueTypeReference() { object.init(); }
- ~QQmlValueTypeReference() { object.destroy(); }
+ void init() {
+ QQmlValueTypeWrapper::init();
+ object.init();
+ }
+ void destroy() {
+ object.destroy();
+ QQmlValueTypeWrapper::destroy();
+ }
QQmlQPointer<QObject> object;
int property;
};
@@ -74,8 +80,7 @@ struct QQmlValueTypeReference : QQmlValueTypeWrapper
struct QQmlValueTypeReference : public QQmlValueTypeWrapper
{
V4_OBJECT2(QQmlValueTypeReference, QQmlValueTypeWrapper)
-
- static void destroy(Heap::Base *that);
+ V4_NEEDS_DESTROY
bool readReferenceValue() const;
};
@@ -86,12 +91,13 @@ DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeReference);
using namespace QV4;
-Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
+void Heap::QQmlValueTypeWrapper::destroy()
{
if (gadgetPtr) {
valueType->metaType.destruct(gadgetPtr);
::operator delete(gadgetPtr);
}
+ Object::destroy();
}
void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
@@ -140,7 +146,7 @@ bool QQmlValueTypeReference::readReferenceValue() const
::operator delete(d()->gadgetPtr);
}
d()->gadgetPtr =0;
- d()->propertyCache = cache;
+ d()->setPropertyCache(cache);
d()->valueType = QQmlValueTypeFactory::valueType(variantReferenceType);
if (!cache)
return false;
@@ -163,7 +169,7 @@ bool QQmlValueTypeReference::readReferenceValue() const
void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4)
{
- if (v4->valueTypeWrapperPrototype()->d())
+ if (v4->valueTypeWrapperPrototype()->d_unchecked())
return;
Scope scope(v4);
@@ -180,7 +186,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>());
r->d()->object = object;
r->d()->property = property;
- r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = 0;
return r->asReturnedValue();
@@ -192,7 +198,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
initProto(engine);
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>());
- r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = 0;
r->d()->setValue(value);
@@ -218,19 +224,13 @@ bool QQmlValueTypeWrapper::toGadget(void *data) const
return true;
}
-void QQmlValueTypeWrapper::destroy(Heap::Base *that)
-{
- Heap::QQmlValueTypeWrapper *w = static_cast<Heap::QQmlValueTypeWrapper *>(that);
- w->Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper();
-}
-
bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
{
Q_ASSERT(m && m->as<QQmlValueTypeWrapper>() && other);
QV4::QQmlValueTypeWrapper *lv = static_cast<QQmlValueTypeWrapper *>(m);
if (QV4::VariantObject *rv = other->as<VariantObject>())
- return lv->isEqual(rv->d()->data);
+ return lv->isEqual(rv->d()->data());
if (QV4::QQmlValueTypeWrapper *v = other->as<QQmlValueTypeWrapper>())
return lv->isEqual(v->toVariant());
@@ -243,7 +243,7 @@ PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name)
Q_ASSERT(m->as<const QQmlValueTypeWrapper>());
const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
- QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(name, 0, 0);
return result ? Attr_Data : Attr_Invalid;
}
@@ -259,8 +259,8 @@ void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value
return;
}
- if (that->d()->propertyCache) {
- const QMetaObject *mo = that->d()->propertyCache->createMetaObject();
+ if (that->d()->propertyCache()) {
+ const QMetaObject *mo = that->d()->propertyCache()->createMetaObject();
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
Scope scope(that->engine());
@@ -335,7 +335,7 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
} else {
result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId))
+ QLatin1Char('(');
- const QMetaObject *mo = w->d()->propertyCache->metaObject();
+ const QMetaObject *mo = w->d()->propertyCache()->metaObject();
const int propCount = mo->propertyCount();
for (int i = 0; i < propCount; ++i) {
if (mo->property(i).isDesignable()) {
@@ -362,7 +362,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
return Primitive::undefinedValue().asReturnedValue();
}
- QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(name, 0, 0);
if (!result)
return Object::get(m, name, hasProperty);
@@ -381,7 +381,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
return QV4::Encode(constructor(v)); \
}
- const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+ const QMetaObject *metaObject = r->d()->propertyCache()->metaObject();
int index = result->coreIndex();
QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
@@ -429,8 +429,8 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
writeBackPropertyType = writebackProperty.userType();
}
- const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
- const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
+ const QMetaObject *metaObject = r->d()->propertyCache()->metaObject();
+ const QQmlPropertyData *pd = r->d()->propertyCache()->property(name, 0, 0);
if (!pd)
return;
@@ -494,9 +494,4 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
}
}
-void QQmlValueTypeReference::destroy(Heap::Base *that)
-{
- static_cast<Heap::QQmlValueTypeReference*>(that)->Heap::QQmlValueTypeReference::~QQmlValueTypeReference();
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 5ef480061d..fec54df770 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -66,14 +66,24 @@ namespace QV4 {
namespace Heap {
struct QQmlValueTypeWrapper : Object {
- QQmlValueTypeWrapper() {}
- ~QQmlValueTypeWrapper();
- QQmlRefPointer<QQmlPropertyCache> propertyCache;
+ void init() { Object::init(); }
+ void destroy();
+ QQmlPropertyCache *propertyCache() const { return _propertyCache; }
+ void setPropertyCache(QQmlPropertyCache *c) {
+ if (c)
+ c->addref();
+ if (_propertyCache)
+ _propertyCache->release();
+ _propertyCache = c;
+ }
mutable void *gadgetPtr;
QQmlValueType *valueType;
void setValue(const QVariant &value) const;
QVariant toVariant() const;
+
+private:
+ QQmlPropertyCache *_propertyCache;
};
}
@@ -82,7 +92,7 @@ struct Q_QML_EXPORT QQmlValueTypeWrapper : Object
{
V4_OBJECT2(QQmlValueTypeWrapper, Object)
V4_PROTOTYPE(valueTypeWrapperPrototype)
- static void destroy(Heap::Base *b);
+ V4_NEEDS_DESTROY
public:
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 6f56931e73..791870b831 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -503,9 +503,9 @@ QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id) const
QV4::Scope scope(cache->engine);
QV4::ScopedValue sv(scope, *(md->data() + id));
const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
- if (!v || v->d()->data.type() != QVariant::Url)
+ if (!v || v->d()->data().type() != QVariant::Url)
return QUrl();
- return v->d()->data.value<QUrl>();
+ return v->d()->data().value<QUrl>();
}
QDate QQmlVMEMetaObject::readPropertyAsDate(int id) const
@@ -517,9 +517,9 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id) const
QV4::Scope scope(cache->engine);
QV4::ScopedValue sv(scope, *(md->data() + id));
const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
- if (!v || v->d()->data.type() != QVariant::Date)
+ if (!v || v->d()->data().type() != QVariant::Date)
return QDate();
- return v->d()->data.value<QDate>();
+ return v->d()->data().value<QDate>();
}
QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
@@ -531,9 +531,9 @@ QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
QV4::Scope scope(cache->engine);
QV4::ScopedValue sv(scope, *(md->data() + id));
const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
- if (!v || v->d()->data.type() != QVariant::DateTime)
+ if (!v || v->d()->data().type() != QVariant::DateTime)
return QDateTime();
- return v->d()->data.value<QDateTime>();
+ return v->d()->data().value<QDateTime>();
}
QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id) const
@@ -545,9 +545,9 @@ QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id) const
QV4::Scope scope(cache->engine);
QV4::ScopedValue sv(scope, *(md->data() + id));
const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
- if (!v || v->d()->data.type() != QVariant::SizeF)
+ if (!v || v->d()->data().type() != QVariant::SizeF)
return QSizeF();
- return v->d()->data.value<QSizeF>();
+ return v->d()->data().value<QSizeF>();
}
QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id) const
@@ -559,9 +559,9 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id) const
QV4::Scope scope(cache->engine);
QV4::ScopedValue sv(scope, *(md->data() + id));
const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
- if (!v || v->d()->data.type() != QVariant::PointF)
+ if (!v || v->d()->data().type() != QVariant::PointF)
return QPointF();
- return v->d()->data.value<QPointF>();
+ return v->d()->data().value<QPointF>();
}
QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id) const
@@ -586,12 +586,12 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const
QV4::Scope scope(cache->engine);
QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id));
- if (!v || (int)v->d()->data.userType() != qMetaTypeId<QList<QObject *> >()) {
+ if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) {
QVariant variant(qVariantFromValue(QList<QObject*>()));
v = cache->engine->newVariantObject(variant);
*(md->data() + id) = v;
}
- return static_cast<QList<QObject *> *>(v->d()->data.data());
+ return static_cast<QList<QObject *> *>(v->d()->data().data());
}
QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) const
@@ -603,9 +603,9 @@ QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) const
QV4::Scope scope(cache->engine);
QV4::ScopedValue sv(scope, *(md->data() + id));
const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
- if (!v || v->d()->data.type() != QVariant::RectF)
+ if (!v || v->d()->data().type() != QVariant::RectF)
return QRectF();
- return v->d()->data.value<QRectF>();
+ return v->d()->data().value<QRectF>();
}
#if defined(Q_OS_WINRT) && defined(_M_ARM)
@@ -740,7 +740,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
QVariant propertyAsVariant;
if (QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
- propertyAsVariant = v->d()->data;
+ propertyAsVariant = v->d()->data();
QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], fallbackMetaType);
}
break;
@@ -816,10 +816,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (!v) {
*(md->data() + id) = cache->engine->newVariantObject(QVariant());
v = (md->data() + id)->as<QV4::VariantObject>();
- QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data);
+ QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data());
}
- needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data);
- QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data);
+ needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data());
+ QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data());
}
break;
case QV4::CompiledData::Property::Var:
@@ -1009,7 +1009,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) const
return QVariant::fromValue(wrapper->object());
const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
if (v)
- return v->d()->data;
+ return v->d()->data();
return cache->engine->toVariant(*(md->data() + id), -1);
}
return QVariant();
@@ -1092,8 +1092,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
if (md) {
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
needActivate = (!v ||
- v->d()->data.userType() != value.userType() ||
- v->d()->data != value);
+ v->d()->data().userType() != value.userType() ||
+ v->d()->data() != value);
if (v)
v->removeVmePropertyReference();
*(md->data() + id) = cache->engine->newVariantObject(value);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index dd517374a5..b4be709b37 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -70,7 +70,7 @@
using namespace QV4;
-#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK)
+#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network)
#define V4THROW_REFERENCE(string) { \
ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \
@@ -174,33 +174,43 @@ public:
namespace Heap {
struct NamedNodeMap : Object {
- NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list);
- ~NamedNodeMap() {
+ void init(NodeImpl *data, const QList<NodeImpl *> &list);
+ void destroy() {
+ delete listPtr;
if (d)
d->release();
+ Object::destroy();
}
- QList<NodeImpl *> list; // Only used in NamedNodeMap
+ QList<NodeImpl *> &list() {
+ if (listPtr == nullptr)
+ listPtr = new QList<NodeImpl *>;
+ return *listPtr;
+ }
+
+ QList<NodeImpl *> *listPtr; // Only used in NamedNodeMap
NodeImpl *d;
};
struct NodeList : Object {
- NodeList(NodeImpl *data);
- ~NodeList() {
+ void init(NodeImpl *data);
+ void destroy() {
if (d)
d->release();
+ Object::destroy();
}
NodeImpl *d;
};
struct NodePrototype : Object {
- NodePrototype();
+ void init();
};
struct Node : Object {
- Node(NodeImpl *data);
- ~Node() {
+ void init(NodeImpl *data);
+ void destroy() {
if (d)
d->release();
+ Object::destroy();
}
NodeImpl *d;
};
@@ -221,10 +231,11 @@ public:
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
-Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list)
- : list(list)
- , d(data)
+void Heap::NamedNodeMap::init(NodeImpl *data, const QList<NodeImpl *> &list)
{
+ Object::init();
+ d = data;
+ this->list() = list;
if (d)
d->addref();
}
@@ -246,9 +257,10 @@ public:
};
-Heap::NodeList::NodeList(NodeImpl *data)
- : d(data)
+void Heap::NodeList::init(NodeImpl *data)
{
+ Object::init();
+ d = data;
if (d)
d->addref();
}
@@ -287,8 +299,9 @@ public:
};
-Heap::NodePrototype::NodePrototype()
+void Heap::NodePrototype::init()
{
+ Object::init();
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
@@ -320,9 +333,10 @@ struct Node : public Object
bool isNull() const;
};
-Heap::Node::Node(NodeImpl *data)
- : d(data)
+void Heap::Node::init(NodeImpl *data)
{
+ Object::init();
+ d = data;
if (d)
d->addref();
}
@@ -878,10 +892,10 @@ ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasPr
const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
- if ((int)index < r->d()->list.count()) {
+ if ((int)index < r->d()->list().count()) {
if (hasProperty)
*hasProperty = true;
- return Node::create(v4, r->d()->list.at(index));
+ return Node::create(v4, r->d()->list().at(index));
}
if (hasProperty)
*hasProperty = false;
@@ -896,14 +910,14 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert
name->makeIdentifier(v4);
if (name->equals(v4->id_length()))
- return Primitive::fromInt32(r->d()->list.count()).asReturnedValue();
+ return Primitive::fromInt32(r->d()->list().count()).asReturnedValue();
QString str = name->toQString();
- for (int ii = 0; ii < r->d()->list.count(); ++ii) {
- if (r->d()->list.at(ii)->name == str) {
+ for (int ii = 0; ii < r->d()->list().count(); ++ii) {
+ if (r->d()->list().at(ii)->name == str) {
if (hasProperty)
*hasProperty = true;
- return Node::create(v4, r->d()->list.at(ii));
+ return Node::create(v4, r->d()->list().at(ii));
}
}
@@ -1588,15 +1602,20 @@ namespace QV4 {
namespace Heap {
struct QQmlXMLHttpRequestWrapper : Object {
- QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request);
- ~QQmlXMLHttpRequestWrapper() {
+ void init(QQmlXMLHttpRequest *request) {
+ Object::init();
+ this->request = request;
+ }
+
+ void destroy() {
delete request;
+ Object::destroy();
}
QQmlXMLHttpRequest *request;
};
struct QQmlXMLHttpRequestCtor : FunctionObject {
- QQmlXMLHttpRequestCtor(ExecutionEngine *engine);
+ void init(ExecutionEngine *engine);
Pointer<Object> proto;
};
@@ -1609,11 +1628,6 @@ struct QQmlXMLHttpRequestWrapper : public Object
V4_NEEDS_DESTROY
};
-Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request)
- : request(request)
-{
-}
-
struct QQmlXMLHttpRequestCtor : public FunctionObject
{
V4_OBJECT2(QQmlXMLHttpRequestCtor, FunctionObject)
@@ -1665,9 +1679,9 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper);
-Heap::QQmlXMLHttpRequestCtor::QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
- : Heap::FunctionObject(engine->rootContext(), QStringLiteral("XMLHttpRequest"))
+void Heap::QQmlXMLHttpRequestCtor::init(ExecutionEngine *engine)
{
+ Heap::FunctionObject::init(engine->rootContext(), QStringLiteral("XMLHttpRequest"));
Scope scope(engine);
Scoped<QV4::QQmlXMLHttpRequestCtor> ctor(scope, this);
@@ -2043,6 +2057,6 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK
+#endif // QT_NO_XMLSTREAMREADER && qml_network
#include <qqmlxmlhttprequest.moc>
diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h
index df30873915..fdb6194537 100644
--- a/src/qml/qml/qqmlxmlhttprequest_p.h
+++ b/src/qml/qml/qqmlxmlhttprequest_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qglobal.h>
#include <private/qqmlglobal_p.h>
-#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK)
+#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network)
QT_BEGIN_NAMESPACE
@@ -64,7 +64,7 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *);
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK
+#endif // QT_NO_XMLSTREAMREADER && qml_network
#endif // QQMLXMLHTTPREQUEST_P_H
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 222b61ae49..cf0fd57773 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -91,10 +91,11 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
-Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
- : enumeratorIterator(0)
- , keyIterator(0)
+void Heap::QtObject::init(QQmlEngine *qmlEngine)
{
+ Heap::Object::init();
+ enumeratorIterator = 0;
+ keyIterator = 0;
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
@@ -1302,17 +1303,18 @@ ReturnedValue QtObject::method_locale(CallContext *ctx)
return QQmlLocale::locale(ctx->engine(), code);
}
-Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction)
- : QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name())
+void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *originalFunction)
{
+ QV4::Heap::FunctionObject::init(originalFunction->scope(), originalFunction->name());
+ bindingLocation = new QQmlSourceLocation;
this->originalFunction = originalFunction->d();
}
void QQmlBindingFunction::initBindingLocation()
{
QV4::StackFrame frame = engine()->currentStackFrame();
- d()->bindingLocation.sourceFile = frame.source;
- d()->bindingLocation.line = frame.line;
+ d()->bindingLocation->sourceFile = frame.source;
+ d()->bindingLocation->line = frame.line;
}
void QQmlBindingFunction::call(const Managed *that, Scope &scope, CallData *callData)
@@ -1436,8 +1438,9 @@ ReturnedValue QtObject::method_get_styleHints(CallContext *ctx)
}
-QV4::Heap::ConsoleObject::ConsoleObject()
+void QV4::Heap::ConsoleObject::init()
{
+ Object::init();
QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
@@ -1559,6 +1562,8 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
return QV4::Encode::undefined();
}
+DEFINE_OBJECT_VTABLE(ConsoleObject);
+
QV4::ReturnedValue ConsoleObject::method_error(CallContext *ctx)
{
return writeToConsole(Error, ctx);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 8c0759679a..7602a92582 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -64,7 +64,7 @@ namespace QV4 {
namespace Heap {
struct QtObject : Object {
- QtObject(QQmlEngine *qmlEngine);
+ void init(QQmlEngine *qmlEngine);
QObject *platform;
QObject *application;
@@ -77,14 +77,18 @@ struct QtObject : Object {
};
struct ConsoleObject : Object {
- ConsoleObject();
+ void init();
};
struct QQmlBindingFunction : FunctionObject {
- QQmlBindingFunction(const QV4::FunctionObject *originalFunction);
+ void init(const QV4::FunctionObject *originalFunction);
+ void destroy() {
+ delete bindingLocation;
+ Object::destroy();
+ }
Pointer<FunctionObject> originalFunction;
// Set when the binding is created later
- QQmlSourceLocation bindingLocation;
+ QQmlSourceLocation *bindingLocation;
};
}
@@ -145,9 +149,7 @@ private:
struct ConsoleObject : Object
{
- typedef Heap::ConsoleObject Data;
- const Data *d() const { return static_cast<const Data *>(Object::d()); }
- Data *d() { return static_cast<Data *>(Object::d()); }
+ V4_OBJECT2(ConsoleObject, Object)
static ReturnedValue method_error(CallContext *ctx);
static ReturnedValue method_log(CallContext *ctx);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index f15020f6c9..b0599dd0a2 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -160,8 +160,10 @@ QV8Engine::~QV8Engine()
qDeleteAll(m_extensionData);
m_extensionData.clear();
+#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network)
qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
m_xmlHttpRequestData = 0;
+#endif
delete m_listModelData;
m_listModelData = 0;
@@ -169,7 +171,7 @@ QV8Engine::~QV8Engine()
delete m_v4Engine;
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *QV8Engine::networkAccessManager()
{
return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
@@ -193,7 +195,7 @@ void QV8Engine::initializeGlobal()
QQmlDateExtension::registerExtension(m_v4Engine);
QQmlNumberExtension::registerExtension(m_v4Engine);
-#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK)
+#if !defined(QT_NO_XMLSTREAMREADER) && QT_CONFIG(qml_network)
qt_add_domexceptions(m_v4Engine);
m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
#endif
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 390831609b..0cbe34fd30 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -188,7 +188,7 @@ public:
void freezeObject(const QV4::Value &value);
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
// Return the network access manager for this engine. By default this returns the network
// access manager of the QQmlEngine. It is overridden in the case of a threaded v8
// instance (like in WorkerScript).
diff --git a/src/qml/qtqmlglobal.h b/src/qml/qtqmlglobal.h
index 34191d06b2..89228b7777 100644
--- a/src/qml/qtqmlglobal.h
+++ b/src/qml/qtqmlglobal.h
@@ -41,6 +41,10 @@
#define QTQMLGLOBAL_H
#include <QtCore/qglobal.h>
+#include <QtQml/qtqml-config.h>
+#if QT_CONFIG(qml_network)
+#include <QtNetwork/qtnetworkglobal.h>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h
index 1b0872298d..63585fd62e 100644
--- a/src/qml/qtqmlglobal_p.h
+++ b/src/qml/qtqmlglobal_p.h
@@ -51,7 +51,9 @@
// We mean it.
//
-#include "qtqmlglobal.h"
+#include <QtCore/private/qglobal_p.h>
+#include <QtQml/private/qtqml-config_p.h>
+#include <QtQml/qtqmlglobal.h>
#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
# define Q_QML_PRIVATE_EXPORT
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index be4258cdfd..c4fabbedcc 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -62,21 +62,26 @@ namespace QV4 {
namespace Heap {
struct DelegateModelGroupFunction : FunctionObject {
- DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg));
+ void init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg));
- uint flag;
QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg);
+ uint flag;
};
struct QQmlDelegateModelGroupChange : Object {
- QQmlDelegateModelGroupChange() {}
+ void init() { Object::init(); }
- QQmlChangeSet::Change change;
+ QQmlChangeSet::ChangeData change;
};
struct QQmlDelegateModelGroupChangeArray : Object {
- QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes);
- QVector<QQmlChangeSet::Change> changes;
+ void init(const QVector<QQmlChangeSet::Change> &changes);
+ void destroy() {
+ delete changes;
+ Object::destroy();
+ }
+
+ QVector<QQmlChangeSet::Change> *changes;
};
@@ -105,11 +110,11 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
}
};
-Heap::DelegateModelGroupFunction::DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
- : QV4::Heap::FunctionObject(scope, QStringLiteral("DelegateModelGroupFunction"))
- , flag(flag)
- , code(code)
+void Heap::DelegateModelGroupFunction::init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
{
+ QV4::Heap::FunctionObject::init(scope, QStringLiteral("DelegateModelGroupFunction"));
+ this->flag = flag;
+ this->code = code;
}
}
@@ -1865,9 +1870,10 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI
DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject);
-QV4::Heap::QQmlDelegateModelItemObject::~QQmlDelegateModelItemObject()
+void QV4::Heap::QQmlDelegateModelItemObject::destroy()
{
item->Dispose();
+ Object::destroy();
}
@@ -3256,8 +3262,8 @@ public:
return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes);
}
- quint32 count() const { return d()->changes.count(); }
- const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); }
+ quint32 count() const { return d()->changes->count(); }
+ const QQmlChangeSet::Change &at(int index) const { return d()->changes->at(index); }
static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty)
{
@@ -3299,9 +3305,10 @@ public:
}
};
-QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes)
- : changes(changes)
+void QV4::Heap::QQmlDelegateModelGroupChangeArray::init(const QVector<QQmlChangeSet::Change> &changes)
{
+ Object::init();
+ this->changes = new QVector<QQmlChangeSet::Change>(changes);
QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(QV4::Heap::ArrayData::Custom);
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 7031cf779c..f4ffdf38aa 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -160,8 +160,8 @@ protected:
namespace QV4 {
namespace Heap {
struct QQmlDelegateModelItemObject : Object {
- inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item);
- ~QQmlDelegateModelItemObject();
+ inline void init(QQmlDelegateModelItem *item);
+ void destroy();
QQmlDelegateModelItem *item;
};
@@ -174,9 +174,10 @@ struct QQmlDelegateModelItemObject : QV4::Object
V4_NEEDS_DESTROY
};
-QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QQmlDelegateModelItem *item)
- : item(item)
+void QV4::Heap::QQmlDelegateModelItemObject::init(QQmlDelegateModelItem *item)
{
+ Object::init();
+ this->item = item;
}
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index 887f5a1edc..ddf77e52c0 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -162,11 +162,13 @@ namespace QV4 {
namespace Heap {
struct ModelObject : public QObjectWrapper {
- ModelObject(QObject *object, QQmlListModel *model, int elementIndex)
- : QObjectWrapper(object)
- , m_model(model)
- , m_elementIndex(elementIndex)
- {}
+ void init(QObject *object, QQmlListModel *model, int elementIndex)
+ {
+ QObjectWrapper::init(object);
+ m_model = model;
+ m_elementIndex = elementIndex;
+ }
+ void destroy() { QObjectWrapper::destroy(); }
QQmlListModel *m_model;
int m_elementIndex;
};
@@ -180,6 +182,7 @@ struct ModelObject : public QObjectWrapper
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
V4_OBJECT2(ModelObject, QObjectWrapper)
+ V4_NEEDS_DESTROY
};
} // namespace QV4
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index b77675df0e..cdcc894da9 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -54,7 +54,7 @@
#include <QtCore/qdatetime.h>
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmlfile.h>
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
#include <QtNetwork/qnetworkaccessmanager.h>
#include "qqmlnetworkaccessmanagerfactory.h"
#endif
@@ -144,7 +144,7 @@ public:
void init();
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *networkAccessManager() override;
#endif
@@ -155,7 +155,7 @@ public:
QV4::PersistentValue onmessage;
private:
QV4::PersistentValue createsend;
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *accessManager;
#endif
};
@@ -202,7 +202,7 @@ private:
QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent)
: QV8Engine(0), p(parent)
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
, accessManager(0)
#endif
{
@@ -211,7 +211,7 @@ QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEn
QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
{
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
delete accessManager;
#endif
}
@@ -274,7 +274,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
return scope.result.asReturnedValue();
}
-#ifndef QT_NO_NETWORK
+#if QT_CONFIG(qml_network)
QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
{
if (!accessManager) {
diff --git a/src/qml/util/qqmlchangeset_p.h b/src/qml/util/qqmlchangeset_p.h
index b7a637fb2e..8e1fa3f9f2 100644
--- a/src/qml/util/qqmlchangeset_p.h
+++ b/src/qml/util/qqmlchangeset_p.h
@@ -68,16 +68,31 @@ public:
int offset;
};
- struct Change
+ // The storrage for Change (below). This struct is trivial, which it has to be in order to store
+ // it in a QV4::Heap::Base object. The Change struct doesn't add any storage fields, so it is
+ // safe to cast ChangeData to/from Change.
+ struct ChangeData
{
- Change() : index(0), count(0), moveId(-1) {}
- Change(int index, int count, int moveId = -1, int offset = 0)
- : index(index), count(count), moveId(moveId), offset(offset) {}
-
int index;
int count;
int moveId;
int offset;
+ };
+
+ struct Change: ChangeData
+ {
+ Change() {
+ index = 0;
+ count = 0;
+ moveId = -1;
+ offset = 0;
+ }
+ Change(int index, int count, int moveId = -1, int offset = 0) {
+ this->index = index;
+ this->count = count;
+ this->moveId = moveId;
+ this->offset = offset;
+ }
bool isMove() const { return moveId >= 0; }