aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf1
-rw-r--r--examples/quick/externaldraganddrop/DragAndDropTextItem.qml92
-rw-r--r--examples/quick/externaldraganddrop/doc/images/qml-dnd2-example.pngbin0 -> 48666 bytes
-rw-r--r--examples/quick/externaldraganddrop/doc/src/externaldraganddrop.qdoc38
-rw-r--r--examples/quick/externaldraganddrop/externaldraganddrop.pro11
-rw-r--r--examples/quick/externaldraganddrop/externaldraganddrop.qml79
-rw-r--r--examples/quick/externaldraganddrop/externaldraganddrop.qmlproject16
-rw-r--r--examples/quick/externaldraganddrop/externaldraganddrop.qrc6
-rw-r--r--examples/quick/externaldraganddrop/main.cpp41
-rw-r--r--examples/quick/quick.pro1
-rw-r--r--src/imports/localstorage/plugin.cpp25
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h14
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp129
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h101
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp46
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h9
-rw-r--r--src/qml/compiler/qv4isel_util_p.h2
-rw-r--r--src/qml/compiler/qv4jsir_p.h6
-rw-r--r--src/qml/compiler/qv4regalloc.cpp3
-rw-r--r--src/qml/compiler/qv4ssa.cpp160
-rw-r--r--src/qml/jsapi/qjsvalue.cpp27
-rw-r--r--src/qml/jsruntime/jsruntime.pri1
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp123
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4context.cpp48
-rw-r--r--src/qml/jsruntime/qv4context_p.h9
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp55
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp18
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h7
-rw-r--r--src/qml/jsruntime/qv4engine.cpp21
-rw-r--r--src/qml/jsruntime/qv4engine_p.h15
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp42
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4function.cpp15
-rw-r--r--src/qml/jsruntime/qv4function_p.h13
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp135
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h36
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp4
-rw-r--r--src/qml/jsruntime/qv4include.cpp9
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp30
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp51
-rw-r--r--src/qml/jsruntime/qv4managed.cpp4
-rw-r--r--src/qml/jsruntime/qv4managed_p.h37
-rw-r--r--src/qml/jsruntime/qv4mm.cpp13
-rw-r--r--src/qml/jsruntime/qv4mm_p.h2
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp93
-rw-r--r--src/qml/jsruntime/qv4object_p.h8
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp21
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h4
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp38
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h6
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp44
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp645
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h509
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h287
-rw-r--r--src/qml/jsruntime/qv4script.cpp9
-rw-r--r--src/qml/jsruntime/qv4script_p.h2
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp18
-rw-r--r--src/qml/jsruntime/qv4stacktrace.cpp2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp64
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4unwindhelper_arm_p.h12
-rw-r--r--src/qml/jsruntime/qv4unwindhelper_dw2_p.h2
-rw-r--r--src/qml/jsruntime/qv4value.cpp85
-rw-r--r--src/qml/jsruntime/qv4value_p.h50
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp132
-rw-r--r--src/qml/qml/qqmlcomponent.cpp41
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp13
-rw-r--r--src/qml/qml/qqmlproperty.cpp10
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp9
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp11
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp11
-rw-r--r--src/qml/qml/v8/qv8engine_p.h4
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp8
-rw-r--r--src/qml/types/qquickworkerscript.cpp27
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp9
-rw-r--r--src/quick/items/qquickclipnode.cpp1
-rw-r--r--src/quick/items/qquickdrag.cpp304
-rw-r--r--src/quick/items/qquickdrag_p.h91
-rw-r--r--src/quick/items/qquickdroparea.cpp223
-rw-r--r--src/quick/items/qquickdroparea_p.h23
-rw-r--r--src/quick/items/qquickimage.cpp19
-rw-r--r--src/quick/items/qquickmousearea.cpp131
-rw-r--r--src/quick/items/qquickmousearea_p.h77
-rw-r--r--src/quick/items/qquicktextinput.cpp3
-rw-r--r--src/quick/items/qquickwindow.cpp97
-rw-r--r--src/quick/items/qquickwindow.h3
-rw-r--r--src/quick/items/qquickwindow_p.h4
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp63
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h3
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp1
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp2
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp1
-rw-r--r--src/quick/scenegraph/util/qsgsimplerectnode.cpp1
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp2
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp21
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp26
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp21
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp4
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp58
-rw-r--r--tests/auto/qml/qv4debugger/tst_qv4debugger.cpp14
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp1
-rw-r--r--tools/v4/main.cpp8
117 files changed, 3236 insertions, 1755 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 6b70079d45..10a0930287 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,5 +1,6 @@
load(qt_build_config)
CONFIG += qt_example_installs
+CONFIG += warning_clean
MODULE_VERSION = 5.2.0
diff --git a/examples/quick/externaldraganddrop/DragAndDropTextItem.qml b/examples/quick/externaldraganddrop/DragAndDropTextItem.qml
new file mode 100644
index 0000000000..390a4b3abe
--- /dev/null
+++ b/examples/quick/externaldraganddrop/DragAndDropTextItem.qml
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+Rectangle {
+ id: item
+ property string display
+ color: "#EEE"
+ Text {
+ anchors.fill: parent
+ text: item.display
+ wrapMode: Text.WordWrap
+ }
+ DropArea {
+ anchors.fill: parent
+ keys: ["text/plain"]
+ onEntered: {
+ item.color = "#FCC"
+ }
+ onExited: {
+ item.color = "#EEE"
+ }
+ onDropped: {
+ item.color = "#EEE"
+ if (drop.hasText) {
+ if (drop.proposedAction == Qt.MoveAction || drop.proposedAction == Qt.CopyAction) {
+ item.display = drop.text
+ drop.acceptProposedAction()
+ }
+ }
+ }
+ }
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ drag.target: draggable
+ }
+ Item {
+ id: draggable
+ anchors.fill: parent
+ Drag.active: mouseArea.drag.active
+ Drag.hotSpot.x: 0
+ Drag.hotSpot.y: 0
+ Drag.mimeData: { "text/plain": item.display }
+ Drag.dragType: Drag.Automatic
+ Drag.onDragStarted: {
+ }
+ Drag.onDragFinished: {
+ if (dropAction == Qt.MoveAction) {
+ item.display = ""
+ }
+ }
+ } // Item
+}
diff --git a/examples/quick/externaldraganddrop/doc/images/qml-dnd2-example.png b/examples/quick/externaldraganddrop/doc/images/qml-dnd2-example.png
new file mode 100644
index 0000000000..e657d81795
--- /dev/null
+++ b/examples/quick/externaldraganddrop/doc/images/qml-dnd2-example.png
Binary files differ
diff --git a/examples/quick/externaldraganddrop/doc/src/externaldraganddrop.qdoc b/examples/quick/externaldraganddrop/doc/src/externaldraganddrop.qdoc
new file mode 100644
index 0000000000..1251e6e1eb
--- /dev/null
+++ b/examples/quick/externaldraganddrop/doc/src/externaldraganddrop.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \title Qt Quick Examples - externaldraganddrop
+ \example externaldraganddrop
+ \brief This is an example of drag and drop between Qml and other applications
+ \image qml-dnd2-example.png
+ \ingroup qtquickexamples
+
+ This example shows you how to respond to do drag and drop using MouseArea and DropArea.
+
+ Drag text between boxes, out of boxes into other applications, and from other applications into the boxes. Use option/ctrl to copy rather than move text when dragging between boxes.
+
+*/
diff --git a/examples/quick/externaldraganddrop/externaldraganddrop.pro b/examples/quick/externaldraganddrop/externaldraganddrop.pro
new file mode 100644
index 0000000000..646781e7d1
--- /dev/null
+++ b/examples/quick/externaldraganddrop/externaldraganddrop.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+QT += quick qml
+SOURCES += main.cpp
+RESOURCES += externaldraganddrop.qrc
+
+EXAMPLE_FILES = \
+ DragAndDropTextItem.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/externaldraganddrop
+INSTALLS += target
diff --git a/examples/quick/externaldraganddrop/externaldraganddrop.qml b/examples/quick/externaldraganddrop/externaldraganddrop.qml
new file mode 100644
index 0000000000..f39d33dda7
--- /dev/null
+++ b/examples/quick/externaldraganddrop/externaldraganddrop.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Layouts 1.0
+
+Item {
+ id: root
+ width: 320
+ height: 480
+
+ ColumnLayout {
+
+ anchors.fill: parent
+ anchors.margins: 8
+
+ Text {
+ Layout.fillWidth: true
+ text: "Drag text into, out of, and between the boxes below."
+ wrapMode: Text.WordWrap
+ }
+
+ DragAndDropTextItem {
+ Layout.fillWidth: true
+ height: 142
+ display: "Sample Text"
+ }
+
+ DragAndDropTextItem {
+ Layout.fillWidth: true
+ height: 142
+ display: "Option/ctrl drag to copy instead of move text."
+ }
+
+ DragAndDropTextItem {
+ Layout.fillWidth: true
+ height: 142
+ display: "Drag out into other applications."
+ }
+
+ }
+}
diff --git a/examples/quick/externaldraganddrop/externaldraganddrop.qmlproject b/examples/quick/externaldraganddrop/externaldraganddrop.qmlproject
new file mode 100644
index 0000000000..359efae597
--- /dev/null
+++ b/examples/quick/externaldraganddrop/externaldraganddrop.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.1
+
+Project {
+ mainFile: "externaldraganddrop.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+}
diff --git a/examples/quick/externaldraganddrop/externaldraganddrop.qrc b/examples/quick/externaldraganddrop/externaldraganddrop.qrc
new file mode 100644
index 0000000000..edac9820c9
--- /dev/null
+++ b/examples/quick/externaldraganddrop/externaldraganddrop.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/externaldraganddrop">
+ <file>externaldraganddrop.qml</file>
+ <file>DragAndDropTextItem.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/externaldraganddrop/main.cpp b/examples/quick/externaldraganddrop/main.cpp
new file mode 100644
index 0000000000..33600e7983
--- /dev/null
+++ b/examples/quick/externaldraganddrop/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(externaldraganddrop/externaldraganddrop)
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index e4c00fffa1..c6b7ee1c34 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
SUBDIRS = quick-accessibility \
animation \
draganddrop \
+ externaldraganddrop \
canvas \
imageelements \
keyinteraction \
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 578c388b44..405acd0f7c 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -60,6 +60,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4exception_p.h>
+#include <private/qv4scopedvalue_p.h>
using namespace QV4;
@@ -340,11 +341,11 @@ static Value qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
ok = false;
db.transaction();
- CALLDATA(1);
- d.thisObject = engine->global();
- d.args[0] = Value::fromObject(w);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = engine->global();
+ callData->args[0] = Value::fromObject(w);
try {
- f->call(d);
+ f->call(callData);
} catch (Exception &) {
db.rollback();
throw;
@@ -394,11 +395,11 @@ static Value qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, bool read
db.transaction();
if (callback) {
- CALLDATA(1);
- d.thisObject = engine->global();
- d.args[0] = Value::fromObject(w);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = engine->global();
+ callData->args[0] = Value::fromObject(w);
try {
- callback->call(d);
+ callback->call(callData);
} catch (Exception &) {
w->inTransaction = false;
db.rollback();
@@ -677,10 +678,10 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
db->version = version;
if (created && dbcreationCallback) {
- CALLDATA(1);
- d.thisObject = engine->global();
- d.args[0] = Value::fromObject(db);
- dbcreationCallback->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = engine->global();
+ callData->args[0] = Value::fromObject(db);
+ dbcreationCallback->call(callData);
}
args->setReturnValue(Value::fromObject(db));
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 404039d4e4..cdcc407e2a 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -57,7 +57,7 @@ namespace CompiledData {
namespace {
bool functionSortHelper(QV4::Function *lhs, QV4::Function *rhs)
{
- return reinterpret_cast<quintptr>(lhs->code) < reinterpret_cast<quintptr>(rhs->code);
+ return reinterpret_cast<quintptr>(lhs->codePtr) < reinterpret_cast<quintptr>(rhs->codePtr);
}
}
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 8164e439f0..68bc109eb4 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -289,7 +289,7 @@ union Instr
struct instr_callValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param dest;
Param result;
};
@@ -297,7 +297,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
@@ -306,14 +306,14 @@ union Instr
Param base;
Param index;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_callActivationProperty {
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_callBuiltinThrow {
@@ -460,7 +460,7 @@ union Instr
struct instr_createValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param func;
Param result;
};
@@ -468,7 +468,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
@@ -476,7 +476,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_jump {
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index cefc053ac4..19c7039e69 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -68,7 +68,7 @@ using namespace QV4;
CompilationUnit::~CompilationUnit()
{
foreach (Function *f, runtimeFunctions)
- engine->allFunctions.remove(reinterpret_cast<quintptr>(f->code));
+ engine->allFunctions.remove(reinterpret_cast<quintptr>(f->codePtr));
UnwindHelper::deregisterFunctions(runtimeFunctions);
}
@@ -87,7 +87,7 @@ void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
UnwindHelper::registerFunctions(runtimeFunctions);
foreach (Function *f, runtimeFunctions)
- engine->allFunctions.insert(reinterpret_cast<quintptr>(f->code), f);
+ engine->allFunctions.insert(reinterpret_cast<quintptr>(f->codePtr), f);
}
QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int functionIndex)
@@ -341,7 +341,7 @@ void Assembler::storeValue(QV4::Value value, V4IR::Temp* destination)
storeValue(value, addr);
}
-void Assembler::enterStandardStackFrame(bool withLocals)
+void Assembler::enterStandardStackFrame()
{
platformEnterStandardStackFrame();
@@ -350,23 +350,22 @@ void Assembler::enterStandardStackFrame(bool withLocals)
push(StackFrameRegister);
move(StackPointerRegister, StackFrameRegister);
- int frameSize = _stackLayout.calculateStackFrameSize(withLocals);
+ int frameSize = _stackLayout.calculateStackFrameSize();
subPtr(TrustedImm32(frameSize), StackPointerRegister);
for (int i = 0; i < calleeSavedRegisterCount; ++i)
storePtr(calleeSavedRegisters[i], Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
- move(StackFrameRegister, LocalsRegister);
}
-void Assembler::leaveStandardStackFrame(bool withLocals)
+void Assembler::leaveStandardStackFrame()
{
// restore the callee saved registers
for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i]);
- int frameSize = _stackLayout.calculateStackFrameSize(withLocals);
+ int frameSize = _stackLayout.calculateStackFrameSize();
// Work around bug in ARMv7Assembler.h where add32(imm, sp, sp) doesn't
// work well for large immediates.
#if CPU(ARM_THUMB2)
@@ -625,7 +624,7 @@ void InstructionSelection::run(V4IR::Function *function)
Assembler* oldAssembler = _as;
_as = new Assembler(this, _function, executableAllocator, 6); // 6 == max argc for calls to built-ins with an argument array
- _as->enterStandardStackFrame(/*withLocals*/true);
+ _as->enterStandardStackFrame();
int contextPointer = 0;
#if !defined(RETURN_VALUE_IN_REGISTER)
@@ -641,13 +640,19 @@ void InstructionSelection::run(V4IR::Function *function)
_as->loadPtr(addressForArgument(contextPointer), Assembler::ContextRegister);
#endif
+ const int locals = _as->stackLayout().calculateJSStackFrameSize();
+ _as->loadPtr(Address(Assembler::ContextRegister, offsetof(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ScratchRegister, offsetof(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
+ _as->addPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, offsetof(ExecutionEngine, jsStackTop)));
+
for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
V4IR::BasicBlock *nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
_block = _function->basicBlocks[i];
_as->registerBlock(_block, nextBlock);
if (_reentryBlocks.contains(_block)) {
- _as->enterStandardStackFrame(/*locals*/false);
+ _as->enterStandardStackFrame();
#ifdef ARGUMENTS_IN_REGISTERS
_as->move(Assembler::registerForArgument(0), Assembler::ContextRegister);
_as->move(Assembler::registerForArgument(1), Assembler::LocalsRegister);
@@ -694,21 +699,19 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, 0);
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_call_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
} else {
generateFunctionCall(Assembler::Void, __qmljs_call_activation_property,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::PointerToString(*func->id),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
}
}
@@ -829,16 +832,21 @@ static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunc
{
*exceptionVar = Value::undefinedValue();
void *addressToContinueAt = 0;
+ Value *jsStackTop = context->engine->jsStackTop;
try {
addressToContinueAt = tryBody(context, localsPtr);
} catch (Exception& ex) {
+ context->engine->jsStackTop = jsStackTop;
ex.accept(context);
*exceptionVar = ex.value();
try {
- ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, ex.value(), context);
+ QV4::ValueScope scope(context);
+ QV4::ScopedValue exception(scope, ex.value());
+ ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, exception, context);
addressToContinueAt = catchBody(catchContext, localsPtr);
context = __qmljs_builtin_pop_scope(catchContext);
} catch (Exception& ex) {
+ context->engine->jsStackTop = jsStackTop;
*exceptionVar = ex.value();
ex.accept(context);
addressToContinueAt = catchBody(context, localsPtr);
@@ -867,7 +875,7 @@ void InstructionSelection::callBuiltinFinishTry()
// This assumes that we're in code that was called by tryWrapper, so we return to try wrapper
// with the address that we'd like to continue at, which is right after the ret below.
Assembler::DataLabelPtr continuation = _as->moveWithPatch(Assembler::TrustedImmPtr(0), Assembler::ReturnValueRegister);
- _as->leaveStandardStackFrame(/*locals*/false);
+ _as->leaveStandardStackFrame();
_as->ret();
_as->addPatch(continuation, _as->label());
}
@@ -976,11 +984,10 @@ void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4
{
Q_ASSERT(value);
- int argc = prepareVariableArguments(args);
- V4IR::Temp* thisObject = 0;
+ int argc = prepareCallData(args, 0);
generateFunctionCall(Assembler::Void, __qmljs_call_value, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(thisObject),
- Assembler::Reference(value), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(value),
+ baseAddressForCallData());
}
void InstructionSelection::loadThisObject(V4IR::Temp *temp)
@@ -1333,19 +1340,19 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
{
assert(base != 0);
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, base);
if (useFastLookups) {
uint index = registerGetterLookup(name);
generateFunctionCall(Assembler::Void, __qmljs_call_property_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
- Assembler::PointerToValue(base), Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
- } else {
+ Assembler::TrustedImm32(index),
+ baseAddressForCallData());
+ } else
+ {
generateFunctionCall(Assembler::Void, __qmljs_call_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base), Assembler::PointerToString(name),
- baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::PointerToString(name),
+ baseAddressForCallData());
}
}
@@ -1354,11 +1361,10 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
{
assert(base != 0);
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, base);
generateFunctionCall(Assembler::Void, __qmljs_call_element, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base),
- Assembler::PointerToValue(index), baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::PointerToValue(index),
+ baseAddressForCallData());
}
void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
@@ -1559,35 +1565,41 @@ void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *t
void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(func != 0);
+ int argc = prepareCallData(args, 0);
if (useFastLookups && func->global) {
- int argc = prepareVariableArguments(args);
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_construct_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
return;
}
- callRuntimeMethod(result, __qmljs_construct_activation_property, func, args);
+ generateFunctionCall(Assembler::Void, __qmljs_construct_activation_property,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::PointerToString(*func->id),
+ baseAddressForCallData());
}
+
void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result)
{
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, 0);
generateFunctionCall(Assembler::Void, __qmljs_construct_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name),
+ baseAddressForCallData());
}
void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(value != 0);
- int argc = prepareVariableArguments(args);
- generateFunctionCall(Assembler::Void, __qmljs_construct_value, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(value), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ int argc = prepareCallData(args, 0);
+ generateFunctionCall(Assembler::Void, __qmljs_construct_value,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::Reference(value),
+ baseAddressForCallData());
}
void InstructionSelection::visitJump(V4IR::Jump *s)
@@ -1740,7 +1752,12 @@ void InstructionSelection::visitRet(V4IR::Ret *s)
Q_UNUSED(s);
}
- _as->leaveStandardStackFrame(/*withLocals*/true);
+ const int locals = _as->stackLayout().calculateJSStackFrameSize();
+ _as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
+ _as->loadPtr(Address(Assembler::ContextRegister, offsetof(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, offsetof(ExecutionEngine, jsStackTop)));
+
+ _as->leaveStandardStackFrame();
#if !defined(ARGUMENTS_IN_REGISTERS) && !defined(RETURN_VALUE_IN_REGISTER)
// Emulate ret(n) instruction
// Pop off return address into scratch register ...
@@ -1769,17 +1786,33 @@ int InstructionSelection::prepareVariableArguments(V4IR::ExprList* args)
return argc;
}
-void InstructionSelection::callRuntimeMethodImp(V4IR::Temp *result, const char* name, ActivationMethod method, V4IR::Expr *base, V4IR::ExprList *args)
+int InstructionSelection::prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject)
{
- V4IR::Name *baseName = base->asName();
- assert(baseName != 0);
+ int argc = 0;
+ for (V4IR::ExprList *it = args; it; it = it->next) {
+ ++argc;
+ }
+
+ Pointer p = _as->stackLayout().callDataAddress(offsetof(CallData, tag));
+ _as->store32(Assembler::TrustedImm32(0), p);
+ p = _as->stackLayout().callDataAddress(offsetof(CallData, argc));
+ _as->store32(Assembler::TrustedImm32(argc), p);
+ p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject));
+ if (!thisObject)
+ _as->storeValue(QV4::Value::undefinedValue(), p);
+ else
+ _as->copyValue(p, thisObject);
- int argc = prepareVariableArguments(args);
- _as->generateFunctionCallImp(Assembler::Void, name, method, Assembler::ContextRegister, Assembler::PointerToValue(result),
- Assembler::PointerToString(*baseName->id), baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ int i = 0;
+ for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
+ V4IR::Expr *arg = it->expr;
+ Q_ASSERT(arg != 0);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(i), arg);
+ }
+ return argc;
}
+
QT_BEGIN_NAMESPACE
namespace QV4 {
bool operator==(const Value &v1, const Value &v2)
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index 588e26a566..ec6780a6f3 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -269,7 +269,7 @@ public:
public:
StackLayout(V4IR::Function *function, int maxArgCountForBuiltins)
: calleeSavedRegCount(Assembler::calleeSavedRegisterCount + 1)
- , maxOutgoingArgumentCount(qMax(function->maxNumberOfArguments, maxArgCountForBuiltins))
+ , maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
, savedConstCount(maxArgCountForBuiltins)
{
@@ -289,15 +289,13 @@ public:
#endif
}
- int calculateStackFrameSize(bool withLocals) const
+ int calculateStackFrameSize() const
{
const int stackSpaceAllocatedOtherwise = StackSpaceAllocatedUponFunctionEntry
+ RegisterSize; // saved StackFrameRegister
- const int locals = withLocals ? (maxOutgoingArgumentCount + localCount + savedConstCount) : 0;
-
- // space for the locals and the callee saved registers
- int frameSize = locals * sizeof(QV4::Value) + RegisterSize * calleeSavedRegisterCount;
+ // space for the callee saved registers
+ int frameSize = RegisterSize * (calleeSavedRegisterCount + savedConstCount);
frameSize = WTF::roundUpToMultipleOf(StackAlignment, frameSize + stackSpaceAllocatedOtherwise);
frameSize -= stackSpaceAllocatedOtherwise;
@@ -305,12 +303,19 @@ public:
return frameSize;
}
+ int calculateJSStackFrameSize() const
+ {
+ const int locals = (localCount + sizeof(QV4::CallData)/sizeof(QV4::Value) - 1 + maxOutgoingArgumentCount) + 1;
+ int frameSize = locals * sizeof(QV4::Value);
+ return frameSize;
+ }
+
Address stackSlotPointer(int idx) const
{
Q_ASSERT(idx >= 0);
Q_ASSERT(idx < localCount);
- Pointer addr = argumentAddressForCall(0);
+ Pointer addr = callDataAddress(0);
addr.offset -= sizeof(QV4::Value) * (idx + 1);
return addr;
}
@@ -323,8 +328,11 @@ public:
Q_ASSERT(argument < maxOutgoingArgumentCount);
const int index = maxOutgoingArgumentCount - argument;
- return Pointer(Assembler::LocalsRegister,
- sizeof(QV4::Value) * (-index) - calleeSavedRegisterSpace());
+ return Pointer(Assembler::LocalsRegister, sizeof(QV4::Value) * (-index));
+ }
+
+ Pointer callDataAddress(int offset = 0) const {
+ return Pointer(Assembler::LocalsRegister, -(sizeof(QV4::CallData) + sizeof(QV4::Value) * (maxOutgoingArgumentCount - 1)) + offset);
}
Address savedRegPointer(int offset) const
@@ -431,6 +439,38 @@ public:
return Pointer(_stackLayout.stackSlotPointer(t->index));
}
+ template <int argumentNumber>
+ void saveOutRegister(PointerToValue arg)
+ {
+ if (!arg.value)
+ return;
+ if (V4IR::Temp *t = arg.value->asTemp()) {
+ if (t->kind == V4IR::Temp::PhysicalRegister) {
+ Pointer addr(_stackLayout.savedRegPointer(argumentNumber));
+ switch (t->type) {
+ case V4IR::BoolType:
+ storeBool((RegisterID) t->index, addr);
+ break;
+ case V4IR::SInt32Type:
+ storeInt32((RegisterID) t->index, addr);
+ break;
+ case V4IR::UInt32Type:
+ storeUInt32((RegisterID) t->index, addr);
+ break;
+ case V4IR::DoubleType:
+ storeDouble((FPRegisterID) t->index, addr);
+ break;
+ default:
+ Q_UNIMPLEMENTED();
+ }
+ }
+ }
+ }
+
+ template <int, typename ArgType>
+ void saveOutRegister(ArgType)
+ {}
+
void loadArgumentInRegister(RegisterID source, RegisterID dest, int argumentNumber)
{
Q_UNUSED(argumentNumber);
@@ -684,8 +724,8 @@ public:
void storeValue(QV4::Value value, V4IR::Temp* temp);
- void enterStandardStackFrame(bool withLocals);
- void leaveStandardStackFrame(bool withLocals);
+ void enterStandardStackFrame();
+ void leaveStandardStackFrame();
template <int argumentNumber, typename T>
void loadArgumentOnStackOrRegister(const T &value)
@@ -747,6 +787,15 @@ public:
sub32(TrustedImm32(stackSpaceNeeded), StackPointerRegister);
}
+ // First save any arguments that reside in registers, because they could be overwritten
+ // if that register is also used to pass arguments.
+ saveOutRegister<5>(arg6);
+ saveOutRegister<4>(arg5);
+ saveOutRegister<3>(arg4);
+ saveOutRegister<2>(arg3);
+ saveOutRegister<1>(arg2);
+ saveOutRegister<0>(arg1);
+
loadArgumentOnStackOrRegister<5>(arg6);
loadArgumentOnStackOrRegister<4>(arg5);
loadArgumentOnStackOrRegister<3>(arg4);
@@ -967,25 +1016,8 @@ public:
if (t->kind != V4IR::Temp::PhysicalRegister)
return loadTempAddress(tmpReg, t);
- Pointer addr(_stackLayout.savedRegPointer(offset));
- switch (t->type) {
- case V4IR::BoolType:
- storeBool((RegisterID) t->index, addr);
- break;
- case V4IR::SInt32Type:
- storeInt32((RegisterID) t->index, addr);
- break;
- case V4IR::UInt32Type:
- storeUInt32((RegisterID) t->index, addr);
- break;
- case V4IR::DoubleType:
- storeDouble((FPRegisterID) t->index, addr);
- break;
- default:
- Q_UNIMPLEMENTED();
- }
- return addr;
+ return Pointer(_stackLayout.savedRegPointer(offset));
}
void storeBool(RegisterID reg, Pointer addr)
@@ -1226,6 +1258,11 @@ protected:
return _as->stackLayout().argumentAddressForCall(0);
}
+ Pointer baseAddressForCallData()
+ {
+ return _as->stackLayout().callDataAddress();
+ }
+
virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
@@ -1300,11 +1337,7 @@ private:
_as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__)
int prepareVariableArguments(V4IR::ExprList* args);
-
- typedef void (*ActivationMethod)(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
- void callRuntimeMethodImp(V4IR::Temp *result, const char* name, ActivationMethod method, V4IR::Expr *base, V4IR::ExprList *args);
-#define callRuntimeMethod(result, function, ...) \
- callRuntimeMethodImp(result, isel_stringIfy(function), function, __VA_ARGS__)
+ int prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject);
template <typename Arg1, typename Arg2>
void generateLookupCall(uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index d4dc5460b7..67433070f6 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -310,7 +310,8 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
Instruction::CallValue call;
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.dest = getParam(value);
call.result = getResultParam(result);
addInstruction(call);
@@ -323,7 +324,8 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
Instruction::CallProperty call;
call.base = getParam(base);
call.name = registerString(name);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -335,7 +337,8 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
Instruction::CallElement call;
call.base = getParam(base);
call.index = getParam(index);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -358,7 +361,8 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
{
Instruction::CreateActivationProperty create;
create.name = registerString(*func->id);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -368,7 +372,8 @@ void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &na
Instruction::CreateProperty create;
create.base = getParam(base);
create.name = registerString(name);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -377,7 +382,8 @@ void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *arg
{
Instruction::CreateValue create;
create.func = getParam(value);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -666,23 +672,15 @@ void InstructionSelection::inplaceMemberOp(V4IR::AluOp oper, V4IR::Temp *source,
addInstruction(imo);
}
-void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 &args)
+void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 *args)
{
- bool singleArgIsTemp = false;
- if (e && e->next == 0 && e->expr->asTemp()) {
- singleArgIsTemp = e->expr->asTemp()->kind == V4IR::Temp::VirtualRegister;
- }
-
- if (singleArgIsTemp) {
- // We pass single arguments as references to the stack, but only if it's not a local or an argument.
- argc = 1;
- args = getParam(e->expr).index;
- } else if (e) {
+ int argLocation = outgoingArgumentTempStart();
+ argc = 0;
+ if (args)
+ *args = argLocation;
+ if (e) {
// We need to move all the temps into the function arg array
- int argLocation = outgoingArgumentTempStart();
assert(argLocation >= 0);
- argc = 0;
- args = argLocation;
while (e) {
Instruction::MoveTemp move;
move.source = getParam(e->expr);
@@ -692,9 +690,6 @@ void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, qui
++argc;
e = e->next;
}
- } else {
- argc = 0;
- args = 0;
}
}
@@ -762,7 +757,8 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
{
Instruction::CallActivationProperty call;
call.name = registerString(*func->id);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -979,7 +975,7 @@ void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const Q
void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc, &call.args);
call.result = getResultParam(result);
addInstruction(call);
}
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index c33c58b627..cf7d1f43e9 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -161,11 +161,12 @@ private:
}
void simpleMove(V4IR::Move *);
- void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 &);
+ void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 * = 0);
- int outgoingArgumentTempStart() const { return _function->tempCount; }
- int scratchTempIndex() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
- int frameSize() const { return scratchTempIndex() + 1; }
+ int scratchTempIndex() const { return _function->tempCount; }
+ int callDataStart() const { return scratchTempIndex() + 1; }
+ int outgoingArgumentTempStart() const { return callDataStart() + offsetof(QV4::CallData, args)/sizeof(QV4::Value); }
+ int frameSize() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
template <int Instr>
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 2e3b64c360..610988ce0c 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -91,6 +91,8 @@ inline QV4::Value convertToValue(V4IR::Const *c)
default:
Q_UNREACHABLE();
}
+ // unreachable, but the function must return something
+ return QV4::Value::undefinedValue();
}
} // namespace QQmlJS
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 1e046b83e3..12f69ac92e 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -183,6 +183,12 @@ enum Type {
StringType = 1 << 7,
ObjectType = 1 << 8
};
+
+inline bool strictlyEqualTypes(Type t1, Type t2)
+{
+ return t1 == t2 || ((t1 & NumberType) && (t2 & NumberType));
+}
+
QString typeName(Type t);
struct ExprVisitor {
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index f82a5fcf1c..1c8bb66fc1 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -307,7 +307,6 @@ protected: // IRDecoder
virtual void loadThisObject(V4IR::Temp *temp)
{
addDef(temp);
- addCall(); // FIXME: propagate this
}
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp)
@@ -813,8 +812,8 @@ private:
foreach (const Move &m, _moves)
if (m.needsSwap)
++swapCount;
-#endif
Q_ASSERT(output.size() == _moves.size() + swapCount);
+#endif
}
#ifdef DEBUG_REGALLOC
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 0b663288ab..528450b73e 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1419,11 +1419,28 @@ protected:
_ty.fullyTyped &= ty.fullyTyped;
}
- // TODO: check & double check the next condition!
- if (_ty.type & ObjectType || _ty.type & UndefinedType || _ty.type & NullType)
- _ty.type = ObjectType;
- else if (_ty.type & NumberType)
- _ty.type = DoubleType;
+ switch (_ty.type) {
+ case UndefinedType:
+ case NullType:
+ case BoolType:
+ case SInt32Type:
+ case UInt32Type:
+ case DoubleType:
+ case StringType:
+ case ObjectType:
+ // The type is not a combination of two or more types, so we're done.
+ break;
+
+ default:
+ // There are multiple types involved, so:
+ if ((_ty.type & NumberType) && !(_ty.type & ~NumberType))
+ // The type is any combination of double/int32/uint32, but nothing else. So we can
+ // type it as double.
+ _ty.type = DoubleType;
+ else
+ // There just is no single type that can hold this combination, so:
+ _ty.type = ObjectType;
+ }
setType(s->targetTemp, _ty.type);
}
@@ -2083,6 +2100,67 @@ void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector
delete bb;
}
}
+
+bool tryOptimizingComparison(Expr *&expr)
+{
+ Binop *b = expr->asBinop();
+ if (!b)
+ return false;
+ Const *leftConst = b->left->asConst();
+ if (!leftConst || leftConst->type == StringType || leftConst->type == ObjectType)
+ return false;
+ Const *rightConst = b->right->asConst();
+ if (!rightConst || rightConst->type == StringType || rightConst->type == ObjectType)
+ return false;
+
+ QV4::Value l = convertToValue(leftConst);
+ QV4::Value r = convertToValue(rightConst);
+
+ switch (b->op) {
+ case OpGt:
+ leftConst->value = __qmljs_cmp_gt(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpLt:
+ leftConst->value = __qmljs_cmp_lt(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpGe:
+ leftConst->value = __qmljs_cmp_ge(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpLe:
+ leftConst->value = __qmljs_cmp_le(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpStrictEqual:
+ if (!strictlyEqualTypes(leftConst->type, rightConst->type))
+ return false;
+ // intentional fall-through
+ case OpEqual:
+ leftConst->value = __qmljs_cmp_eq(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpStrictNotEqual:
+ if (!strictlyEqualTypes(leftConst->type, rightConst->type))
+ return false;
+ // intentional fall-through
+ case OpNotEqual:
+ leftConst->value = __qmljs_cmp_ne(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
} // anonymous namespace
void optimizeSSA(Function *function, DefUsesCalculator &defUses)
@@ -2229,7 +2307,61 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
continue;
}
- // TODO: Constant binary expression evaluation
+ if (Binop *b = m->source->asBinop()) {
+ // TODO: More constant binary expression evaluation
+ // TODO: If the result of the move is only used in one single cjump, then
+ // inline the binop into the cjump.
+ Const *leftConst = b->left->asConst();
+ if (!leftConst || leftConst->type == StringType || leftConst->type == ObjectType)
+ continue;
+ Const *rightConst = b->right->asConst();
+ if (!rightConst || rightConst->type == StringType || rightConst->type == ObjectType)
+ continue;
+
+ QV4::Value lc = convertToValue(leftConst);
+ QV4::Value rc = convertToValue(rightConst);
+ double l = __qmljs_to_number(&lc);
+ double r = __qmljs_to_number(&rc);
+
+ switch (b->op) {
+ case OpMul:
+ leftConst->value = l * r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpAdd:
+ leftConst->value = l + r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpSub:
+ leftConst->value = l - r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpDiv:
+ leftConst->value = l / r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpMod:
+ leftConst->value = std::fmod(l, r);
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ default:
+ if (tryOptimizingComparison(m->source))
+ W += m;
+ break;
+ }
+
+ continue;
+ }
}
} else if (CJump *cjump = s->asCJump()) {
if (Const *c = cjump->cond->asConst()) {
@@ -2246,9 +2378,12 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
*ref[s] = jump;
continue;
+ } else if (cjump->cond->asBinop()) {
+ if (tryOptimizingComparison(cjump->cond))
+ W += cjump;
+ continue;
}
// TODO: Constant unary expression evaluation
- // TODO: Constant binary expression evaluation
}
}
@@ -2580,9 +2715,10 @@ void Optimizer::run()
// showMeTheCode(function);
+ static bool doSSA = /*qgetenv("QV4_NO_SSA").isEmpty();*/ false;
static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
- if (!function->hasTry && !function->hasWith && doOpt) {
+ if (!function->hasTry && !function->hasWith && doSSA) {
// qout << "Starting edge splitting..." << endl;
splitCriticalEdges(function);
// showMeTheCode(function);
@@ -2605,9 +2741,11 @@ void Optimizer::run()
DeadCodeElimination(defUses, function).run();
// showMeTheCode(function);
-// qout << "Running SSA optimization..." << endl;
- optimizeSSA(function, defUses);
-// showMeTheCode(function);
+ if (doOpt) {
+// qout << "Running SSA optimization..." << endl;
+ optimizeSSA(function, defUses);
+// showMeTheCode(function);
+ }
// qout << "Running type inference..." << endl;
TypeInference(defUses).run(function);
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index b737ee0073..f18814cedf 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -55,6 +55,7 @@
#include "private/qv8engine_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4exception_p.h>
+#include <private/qv4scopedvalue_p.h>
QV4::Value QJSValuePrivate::getValue(QV4::ExecutionEngine *e)
{
@@ -505,20 +506,20 @@ QJSValue QJSValue::call(const QJSValueList &args)
ExecutionEngine *engine = d->engine;
assert(engine);
- CALLDATA(args.length());
- d.thisObject = Value::fromObject(engine->globalObject);
+ ScopedCallData callData(engine, args.length());
+ callData->thisObject = Value::fromObject(engine->globalObject);
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- d.args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = args.at(i).d->getValue(engine);
}
Value result;
QV4::ExecutionContext *ctx = engine->current;
try {
- result = f->call(d);
+ result = f->call(callData);
} catch (Exception &e) {
e.accept(ctx);
result = e.value();
@@ -561,20 +562,20 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
return QJSValue();
}
- CALLDATA(args.size());
- d.thisObject = instance.d->getValue(engine);
+ ScopedCallData callData(engine, args.size());
+ callData->thisObject = instance.d->getValue(engine);
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- d.args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = args.at(i).d->getValue(engine);
}
Value result;
QV4::ExecutionContext *ctx = engine->current;
try {
- result = f->call(d);
+ result = f->call(callData);
} catch (Exception &e) {
e.accept(ctx);
result = e.value();
@@ -610,19 +611,19 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
ExecutionEngine *engine = d->engine;
assert(engine);
- CALLDATA(args.size());
+ ScopedCallData callData(engine, args.size());
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
return QJSValue();
}
- d.args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = args.at(i).d->getValue(engine);
}
Value result;
QV4::ExecutionContext *ctx = engine->current;
try {
- result = f->construct(d);
+ result = f->construct(callData);
} catch (Exception &e) {
e.accept(ctx);
result = e.value();
@@ -742,7 +743,7 @@ QJSValue& QJSValue::operator=(const QJSValue& other)
*/
bool QJSValue::equals(const QJSValue& other) const
{
- return __qmljs_cmp_eq(d->value, other.d->value);
+ return __qmljs_cmp_eq(QV4::ValueRef(d), QV4::ValueRef(other.d));
}
/*!
@@ -769,7 +770,7 @@ bool QJSValue::equals(const QJSValue& other) const
*/
bool QJSValue::strictlyEquals(const QJSValue& other) const
{
- return __qmljs_strict_equal(d->value, other.d->value);
+ return __qmljs_strict_equal(QV4::ValueRef(d), QV4::ValueRef(other.d));
}
/*!
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 9a1325b58a..c504f750e9 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -90,6 +90,7 @@ HEADERS += \
$$PWD/qv4unwindhelper_arm_p.h \
$$PWD/qv4serialize_p.h \
$$PWD/qv4script_p.h \
+ $$PWD/qv4scopedvalue_p.h \
$$PWD/qv4util_p.h \
$$PWD/qv4executableallocator_p.h \
$$PWD/qv4sequenceobject_p.h \
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 7ac74c1197..5a53c0fc3e 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <qv4argumentsobject_p.h>
#include <qv4alloca_p.h>
+#include <qv4scopedvalue_p.h>
using namespace QV4;
@@ -129,10 +130,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
if (isMapped && attrs.isData()) {
if (!attrs.isGeneric()) {
- CALLDATA(1);
- d.thisObject = Value::fromObject(this);
- d.args[0] = desc.value;
- map.setter()->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = Value::fromObject(this);
+ callData->args[0] = desc.value;
+ map.setter()->call(callData);
}
if (attrs.isWritable()) {
*pd = map;
@@ -147,10 +148,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
DEFINE_MANAGED_VTABLE(ArgumentsGetterFunction);
-Value ArgumentsGetterFunction::call(Managed *getter, const CallData &d)
+Value ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
{
ArgumentsGetterFunction *g = static_cast<ArgumentsGetterFunction *>(getter);
- Object *that = d.thisObject.asObject();
+ Object *that = callData->thisObject.asObject();
if (!that)
getter->engine()->current->throwTypeError();
ArgumentsObject *o = that->asArgumentsObject();
@@ -163,10 +164,10 @@ Value ArgumentsGetterFunction::call(Managed *getter, const CallData &d)
DEFINE_MANAGED_VTABLE(ArgumentsSetterFunction);
-Value ArgumentsSetterFunction::call(Managed *setter, const CallData &d)
+Value ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
{
ArgumentsSetterFunction *s = static_cast<ArgumentsSetterFunction *>(setter);
- Object *that = d.thisObject.asObject();
+ Object *that = callData->thisObject.asObject();
if (!that)
setter->engine()->current->throwTypeError();
ArgumentsObject *o = that->asArgumentsObject();
@@ -174,7 +175,7 @@ Value ArgumentsSetterFunction::call(Managed *setter, const CallData &d)
setter->engine()->current->throwTypeError();
assert(s->index < o->context->argumentCount);
- o->context->arguments[s->index] = d.argc ? d.args[0] : Value::undefinedValue();
+ o->context->arguments[s->index] = callData->argc ? callData->args[0] : Value::undefinedValue();
return Value::undefinedValue();
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index f48db1f2e6..66ee22c953 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -55,7 +55,7 @@ struct ArgumentsGetterFunction: FunctionObject
ArgumentsGetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *d);
protected:
static const ManagedVTable static_vtbl;
@@ -68,7 +68,7 @@ struct ArgumentsSetterFunction: FunctionObject
ArgumentsSetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 6fc661565d..e3b08f5941 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -42,6 +42,7 @@
#include "qv4arrayobject_p.h"
#include "qv4sparsearray_p.h"
#include "qv4objectproto_p.h"
+#include "qv4scopedvalue_p.h"
using namespace QV4;
@@ -53,25 +54,25 @@ ArrayCtor::ArrayCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ArrayCtor::construct(Managed *m, const CallData &d)
+Value ArrayCtor::construct(Managed *m, CallData *callData)
{
ExecutionEngine *v4 = m->engine();
ArrayObject *a = v4->newArrayObject();
uint len;
- if (d.argc == 1 && d.args[0].isNumber()) {
+ if (callData->argc == 1 && callData->args[0].isNumber()) {
bool ok;
- len = d.args[0].asArrayLength(&ok);
+ len = callData->args[0].asArrayLength(&ok);
if (!ok)
- v4->current->throwRangeError(d.args[0]);
+ v4->current->throwRangeError(callData->args[0]);
if (len < 0x1000)
a->arrayReserve(len);
} else {
- len = d.argc;
+ len = callData->argc;
a->arrayReserve(len);
for (unsigned int i = 0; i < len; ++i)
- a->arrayData[i].value = d.args[i];
+ a->arrayData[i].value = callData->args[i];
a->arrayDataLen = len;
}
a->setArrayLengthUnchecked(len);
@@ -79,9 +80,9 @@ Value ArrayCtor::construct(Managed *m, const CallData &d)
return Value::fromObject(a);
}
-Value ArrayCtor::call(Managed *that, const CallData &d)
+Value ArrayCtor::call(Managed *that, CallData *callData)
{
- return construct(that, d);
+ return construct(that, callData);
}
ArrayPrototype::ArrayPrototype(InternalClass *ic)
@@ -137,8 +138,8 @@ Value ArrayPrototype::method_toString(SimpleCallContext *ctx)
QV4::Object *o = ctx->thisObject.toObject(ctx);
FunctionObject *f = o->get(ctx->engine->newString("join")).asFunctionObject();
if (f) {
- CALLDATA(0);
- d.thisObject = ctx->thisObject;
+ ScopedCallData d(ctx->engine, 0);
+ d->thisObject = ctx->thisObject;
return f->call(d);
}
return ObjectPrototype::method_toString(ctx);
@@ -545,12 +546,14 @@ Value ArrayPrototype::method_unshift(SimpleCallContext *ctx)
Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len)
return Value::fromInt32(-1);
- Value searchValue;
+ ScopedValue searchValue(scope);
uint fromIndex = 0;
if (ctx->argumentCount >= 1)
@@ -568,9 +571,10 @@ Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
}
if (instance->isStringObject()) {
+ ScopedValue v(scope);
for (uint k = fromIndex; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (exists && __qmljs_strict_equal(v, searchValue))
return Value::fromDouble(k);
}
@@ -582,12 +586,14 @@ Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len)
return Value::fromInt32(-1);
- Value searchValue;
+ ScopedValue searchValue(scope);
uint fromIndex = len;
if (ctx->argumentCount >= 1)
@@ -607,10 +613,11 @@ Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
fromIndex = (uint) f + 1;
}
+ ScopedValue v(scope);
for (uint k = fromIndex; k > 0;) {
--k;
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (exists && __qmljs_strict_equal(v, searchValue))
return Value::fromDouble(k);
}
@@ -636,12 +643,12 @@ Value ArrayPrototype::method_every(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value r = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ callData->thisObject = thisArg;
+ Value r = callback->call(callData);
ok = r.toBoolean();
}
return Value::fromBoolean(ok);
@@ -665,12 +672,12 @@ Value ArrayPrototype::method_some(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value r = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ Value r = callback->call(callData);
if (r.toBoolean())
return Value::fromBoolean(true);
}
@@ -695,12 +702,12 @@ Value ArrayPrototype::method_forEach(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ callback->call(callData);
}
return Value::undefinedValue();
}
@@ -727,12 +734,12 @@ Value ArrayPrototype::method_map(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value mapped = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ Value mapped = callback->call(callData);
a->arraySet(k, mapped);
}
return Value::fromObject(a);
@@ -760,12 +767,12 @@ Value ArrayPrototype::method_filter(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value selected = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ Value selected = callback->call(callData);
if (selected.toBoolean()) {
a->arraySet(to, v);
++to;
@@ -804,13 +811,13 @@ Value ArrayPrototype::method_reduce(SimpleCallContext *ctx)
bool kPresent;
Value v = instance->getIndexed(k, &kPresent);
if (kPresent) {
- CALLDATA(4);
- d.args[0] = acc;
- d.args[1] = v;
- d.args[2] = Value::fromDouble(k);
- d.args[3] = Value::fromObject(instance);
- d.thisObject = Value::undefinedValue();
- acc = callback->call(d);
+ ScopedCallData callData(ctx->engine, 4);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = acc;
+ callData->args[1] = v;
+ callData->args[2] = Value::fromDouble(k);
+ callData->args[3] = Value::fromObject(instance);
+ acc = callback->call(callData);
}
++k;
}
@@ -853,13 +860,13 @@ Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx)
bool kPresent;
Value v = instance->getIndexed(k - 1, &kPresent);
if (kPresent) {
- CALLDATA(4);
- d.args[0] = acc;
- d.args[1] = v;
- d.args[2] = Value::fromDouble(k - 1);
- d.args[3] = Value::fromObject(instance);
- d.thisObject = Value::undefinedValue();
- acc = callback->call(d);
+ ScopedCallData callData(ctx->engine, 4);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = acc;
+ callData->args[1] = v;
+ callData->args[2] = Value::fromDouble(k - 1);
+ callData->args[3] = Value::fromObject(instance);
+ acc = callback->call(callData);
}
--k;
}
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 0d76542535..354ddd0380 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -53,8 +53,8 @@ struct ArrayCtor: FunctionObject
{
ArrayCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 25c105210a..6b77db3ca7 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -51,15 +51,15 @@ BooleanCtor::BooleanCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value BooleanCtor::construct(Managed *m, const CallData &d)
+Value BooleanCtor::construct(Managed *m, CallData *callData)
{
- bool n = d.argc ? d.args[0].toBoolean() : false;
+ bool n = callData->argc ? callData->args[0].toBoolean() : false;
return Value::fromObject(m->engine()->newBooleanObject(Value::fromBoolean(n)));
}
-Value BooleanCtor::call(Managed *, const CallData &d)
+Value BooleanCtor::call(Managed *, CallData *callData)
{
- bool value = d.argc ? d.args[0].toBoolean() : 0;
+ bool value = callData->argc ? callData->args[0].toBoolean() : 0;
return Value::fromBoolean(value);
}
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index b55f82b76f..35ecf25b6f 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -53,8 +53,8 @@ struct BooleanCtor: FunctionObject
{
BooleanCtor(ExecutionContext *scope);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 29fdc333f8..1e42a186a0 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -51,7 +51,7 @@
using namespace QV4;
-CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *function, const CallData &d)
+CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *function, CallData *callData)
{
CallContext *c = (CallContext *)stackSpace;
#ifndef QT_NO_DEBUG
@@ -63,10 +63,11 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *
c->initBaseContext(Type_CallContext, engine, this);
c->function = function;
- c->arguments = d.args;
- c->realArgumentCount = d.argc;
- c->argumentCount = d.argc;
- c->thisObject = d.thisObject;
+ // ###
+ c->arguments = const_cast<Value *>(callData->args);
+ c->realArgumentCount = callData->argc;
+ c->argumentCount = callData->argc;
+ c->thisObject = callData->thisObject;
c->strictMode = function->strictMode;
c->marked = false;
@@ -89,30 +90,28 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *
if (function->varCount)
std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue());
- if (d.argc < function->formalParameterCount) {
+ if (callData->argc < function->formalParameterCount) {
#ifndef QT_NO_DEBUG
Q_ASSERT(function->formalParameterCount <= QV4::Global::ReservedArgumentCount);
#endif
- std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
+ std::fill(c->arguments + callData->argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
c->argumentCount = function->formalParameterCount;
}
return c;
}
-CallContext *ExecutionContext::newCallContext(FunctionObject *function, const CallData &d)
+CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
{
- CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, d.argc)));
+ CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, callData->argc)));
engine->current = c;
c->initBaseContext(Type_CallContext, engine, this);
c->function = function;
- c->arguments = d.args;
- c->realArgumentCount = d.argc;
- c->argumentCount = d.argc;
- c->thisObject = d.thisObject;
+ c->realArgumentCount = callData->argc;
+ c->thisObject = callData->thisObject;
c->strictMode = function->strictMode;
c->marked = false;
@@ -135,12 +134,12 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, const Ca
if (function->varCount)
std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue());
- c->argumentCount = qMax((uint)d.argc, function->formalParameterCount);
+ c->argumentCount = qMax((uint)callData->argc, function->formalParameterCount);
c->arguments = c->locals + function->varCount;
- if (d.argc)
- ::memcpy(c->arguments, d.args, c->realArgumentCount * sizeof(Value));
- if (d.argc < function->formalParameterCount)
- std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
+ if (callData->argc)
+ ::memcpy(c->arguments, callData->args, callData->argc * sizeof(Value));
+ if (callData->argc < function->formalParameterCount)
+ std::fill(c->arguments + callData->argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
return c;
}
@@ -595,18 +594,11 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
}
-
-void ExecutionContext::inplaceBitOp(String *name, const Value &value, BinOp op)
-{
- Value lhs = getProperty(name);
- Value result;
- op(&result, lhs, value);
- setProperty(name, result);
-}
-
void ExecutionContext::throwError(const Value &value)
{
- __qmljs_throw(this, value);
+ ValueScope scope(this);
+ ScopedValue v(scope, value);
+ __qmljs_throw(this, v);
}
void ExecutionContext::throwError(const QString &message)
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 331c5aa990..fe10e33c5e 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -42,7 +42,8 @@
#define QMLJS_ENVIRONMENT_H
#include "qv4global_p.h"
-#include "qv4runtime_p.h"
+#include "qv4value_def_p.h"
+#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
@@ -52,6 +53,7 @@ struct Object;
struct ExecutionEngine;
struct DeclarativeEnvironment;
struct Lookup;
+struct Function;
namespace CompiledData {
struct CompilationUnit;
@@ -114,8 +116,8 @@ struct Q_QML_EXPORT ExecutionContext
interpreterInstructionPointer = 0;
}
- CallContext *newCallContext(void *stackSpace, FunctionObject *f, const CallData &d);
- CallContext *newCallContext(FunctionObject *f, const CallData &d);
+ CallContext *newCallContext(void *stackSpace, FunctionObject *f, CallData *callData);
+ CallContext *newCallContext(FunctionObject *f, CallData *callData);
WithContext *newWithContext(Object *with);
CatchContext *newCatchContext(String* exceptionVarName, const QV4::Value &exceptionValue);
CallContext *newQmlContext(FunctionObject *f, Object *qml);
@@ -143,7 +145,6 @@ struct Q_QML_EXPORT ExecutionContext
Value getProperty(String *name);
Value getPropertyNoThrow(String *name);
Value getPropertyAndBase(String *name, Object **base);
- void inplaceBitOp(String *name, const QV4::Value &value, BinOp op);
bool deleteProperty(String *name);
inline Value argument(unsigned int index = 0);
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 9f25b8dc40..1ef4aec246 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -42,7 +42,7 @@
#include "qv4dateobject_p.h"
#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -55,11 +55,6 @@
#include <time.h>
#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
-#include <qv4jsir_p.h>
-#include <qv4codegen_p.h>
#include <wtf/MathExtras.h>
@@ -659,34 +654,35 @@ DateCtor::DateCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value DateCtor::construct(Managed *m, const CallData &d)
+Value DateCtor::construct(Managed *m, CallData *callData)
{
double t = 0;
- if (d.argc == 0)
+ if (callData->argc == 0)
t = currentTime();
- else if (d.argc == 1) {
- Value arg = d.args[0];
- if (DateObject *d = arg.asDateObject())
+ else if (callData->argc == 1) {
+ ValueScope scope(m->engine());
+ ScopedValue arg(scope, callData->args[0]);
+ if (DateObject *d = arg->asDateObject())
arg = d->value;
else
arg = __qmljs_to_primitive(arg, PREFERREDTYPE_HINT);
- if (arg.isString())
- t = ParseString(arg.stringValue()->toQString());
+ if (arg->isString())
+ t = ParseString(arg->stringValue()->toQString());
else
- t = TimeClip(arg.toNumber());
+ t = TimeClip(arg->toNumber());
}
else { // d.argc > 1
- double year = d.args[0].toNumber();
- double month = d.args[1].toNumber();
- double day = d.argc >= 3 ? d.args[2].toNumber() : 1;
- double hours = d.argc >= 4 ? d.args[3].toNumber() : 0;
- double mins = d.argc >= 5 ? d.args[4].toNumber() : 0;
- double secs = d.argc >= 6 ? d.args[5].toNumber() : 0;
- double ms = d.argc >= 7 ? d.args[6].toNumber() : 0;
+ double year = callData->args[0].toNumber();
+ double month = callData->args[1].toNumber();
+ double day = callData->argc >= 3 ? callData->args[2].toNumber() : 1;
+ double hours = callData->argc >= 4 ? callData->args[3].toNumber() : 0;
+ double mins = callData->argc >= 5 ? callData->args[4].toNumber() : 0;
+ double secs = callData->argc >= 6 ? callData->args[5].toNumber() : 0;
+ double ms = callData->argc >= 7 ? callData->args[6].toNumber() : 0;
if (year >= 0 && year <= 99)
year += 1900;
t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms));
@@ -697,7 +693,7 @@ Value DateCtor::construct(Managed *m, const CallData &d)
return Value::fromObject(o);
}
-Value DateCtor::call(Managed *m, const CallData &)
+Value DateCtor::call(Managed *m, CallData *)
{
double t = currentTime();
return Value::fromString(m->engine()->current, ToString(t));
@@ -1295,20 +1291,21 @@ Value DatePrototype::method_toISOString(SimpleCallContext *ctx)
Value DatePrototype::method_toJSON(SimpleCallContext *ctx)
{
- Value O = __qmljs_to_object(ctx, ctx->thisObject);
- Value tv = __qmljs_to_primitive(O, NUMBER_HINT);
+ ValueScope scope(ctx);
+ ScopedValue O(scope, __qmljs_to_object(ctx, ValueRef(&ctx->thisObject)));
+ ScopedValue tv(scope, __qmljs_to_primitive(O, NUMBER_HINT));
- if (tv.isNumber() && !std::isfinite(tv.toNumber()))
+ if (tv->isNumber() && !std::isfinite(tv->toNumber()))
return Value::nullValue();
- FunctionObject *toIso = O.objectValue()->get(ctx->engine->newString(QStringLiteral("toISOString"))).asFunctionObject();
+ FunctionObject *toIso = O->objectValue()->get(ctx->engine->newString(QStringLiteral("toISOString"))).asFunctionObject();
if (!toIso)
ctx->throwTypeError();
- CALLDATA(0);
- d.thisObject = ctx->thisObject;
- return toIso->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = ctx->thisObject;
+ return toIso->call(callData);
}
void DatePrototype::timezoneUpdated()
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 238d10849a..573326adc4 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -66,8 +66,8 @@ struct DateCtor: FunctionObject
{
DateCtor(ExecutionContext *scope);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 5534305068..10f22a11b8 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -298,19 +298,27 @@ void DebuggerAgent::removeDebugger(Debugger *debugger)
debugger->detachFromAgent();
}
-void DebuggerAgent::pause(Debugger *debugger)
+void DebuggerAgent::pause(Debugger *debugger) const
{
debugger->pause();
}
-void DebuggerAgent::addBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber)
+void DebuggerAgent::pauseAll() const
{
- debugger->addBreakPoint(fileName, lineNumber);
+ foreach (Debugger *debugger, m_debuggers)
+ pause(debugger);
}
-void DebuggerAgent::removeBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber)
+void DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber) const
{
- debugger->removeBreakPoint(fileName, lineNumber);
+ foreach (Debugger *debugger, m_debuggers)
+ debugger->addBreakPoint(fileName, lineNumber);
+}
+
+void DebuggerAgent::removeBreakPoint(const QString &fileName, int lineNumber) const
+{
+ foreach (Debugger *debugger, m_debuggers)
+ debugger->removeBreakPoint(fileName, lineNumber);
}
DebuggerAgent::~DebuggerAgent()
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index d71b25f378..908854865d 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -140,9 +140,10 @@ public:
void addDebugger(Debugger *debugger);
void removeDebugger(Debugger *debugger);
- void pause(Debugger *debugger);
- void addBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber);
- void removeBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber);
+ void pause(Debugger *debugger) const;
+ void pauseAll() const;
+ void addBreakPoint(const QString &fileName, int lineNumber) const;
+ void removeBreakPoint(const QString &fileName, int lineNumber) const;
Q_INVOKABLE virtual void debuggerPaused(QV4::Debugging::Debugger *debugger) = 0;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index ae444ab938..638609de37 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -84,6 +84,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
+ , jsStack(new WTF::PageAllocation)
, debugger(0)
, globalObject(0)
, globalCode(0)
@@ -95,8 +96,13 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
MemoryManager::GCBlocker gcBlocker(memoryManager);
if (!factory) {
+
#ifdef V4_ENABLE_JIT
- factory = new QQmlJS::MASM::ISelFactory;
+ static const bool forceMoth = !qgetenv("QV4_FORCE_INTERPRETER").isEmpty();
+ if (forceMoth)
+ factory = new QQmlJS::Moth::ISelFactory;
+ else
+ factory = new QQmlJS::MASM::ISelFactory;
#else // !V4_ENABLE_JIT
factory = new QQmlJS::Moth::ISelFactory;
#endif // V4_ENABLE_JIT
@@ -105,6 +111,11 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
memoryManager->setExecutionEngine(this);
+ // reserve 8MB for the JS stack
+ *jsStack = WTF::PageAllocation::allocate(8*1024*1024, WTF::OSAllocator::JSVMStackPages, true);
+ jsStackBase = (Value *)jsStack->base();
+ jsStackTop = jsStackBase;
+
identifierTable = new IdentifierTable(this);
emptyClass = new (classPool.allocate(sizeof(InternalClass))) InternalClass(this);
@@ -291,6 +302,8 @@ ExecutionEngine::~ExecutionEngine()
delete regExpCache;
delete regExpAllocator;
delete executableAllocator;
+ jsStack->deallocate();
+ delete jsStack;
}
void ExecutionEngine::enableDebugger()
@@ -708,13 +721,13 @@ namespace {
{
bool operator()(Function *function, quintptr pc)
{
- return reinterpret_cast<quintptr>(function->code) < pc
- && (reinterpret_cast<quintptr>(function->code) + function->codeSize) < pc;
+ return reinterpret_cast<quintptr>(function->codePtr) < pc
+ && (reinterpret_cast<quintptr>(function->codePtr) + function->codeSize) < pc;
}
bool operator()(quintptr pc, Function *function)
{
- return pc < reinterpret_cast<quintptr>(function->code);
+ return pc < reinterpret_cast<quintptr>(function->codePtr);
}
};
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index b7b27a48f9..1dbffa28aa 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -50,6 +50,7 @@
namespace WTF {
class BumpPointerAllocator;
+class PageAllocation;
}
QT_BEGIN_NAMESPACE
@@ -123,6 +124,20 @@ struct Q_QML_EXPORT ExecutionEngine
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
+ WTF::PageAllocation *jsStack;
+ Value *jsStackBase;
+ Value *jsStackTop;
+
+ Value *stackPush(uint nValues) {
+ Value *ptr = jsStackTop;
+ jsStackTop = ptr + nValues;
+ return ptr;
+ }
+
+ void stackPop(uint nValues) {
+ jsStackTop -= nValues;
+ }
+
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 04357c393a..6174c9a7f5 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -240,14 +240,14 @@ ErrorCtor::ErrorCtor(ExecutionContext *scope, String *name)
vtbl = &static_vtbl;
}
-Value ErrorCtor::construct(Managed *m, const CallData &d)
+Value ErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(m->engine()->newErrorObject(d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(m->engine()->newErrorObject(callData->argc ? callData->args[0] : Value::undefinedValue()));
}
-Value ErrorCtor::call(Managed *that, const CallData &d)
+Value ErrorCtor::call(Managed *that, CallData *callData)
{
- return that->construct(d);
+ return that->construct(callData);
}
EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
@@ -256,9 +256,9 @@ EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value EvalErrorCtor::construct(Managed *m, const CallData &d)
+Value EvalErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
@@ -267,9 +267,9 @@ RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value RangeErrorCtor::construct(Managed *m, const CallData &d)
+Value RangeErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
@@ -278,9 +278,9 @@ ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ReferenceErrorCtor::construct(Managed *m, const CallData &d)
+Value ReferenceErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
@@ -289,9 +289,9 @@ SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value SyntaxErrorCtor::construct(Managed *m, const CallData &d)
+Value SyntaxErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
@@ -300,9 +300,9 @@ TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value TypeErrorCtor::construct(Managed *m, const CallData &d)
+Value TypeErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
@@ -311,9 +311,9 @@ URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value URIErrorCtor::construct(Managed *m, const CallData &d)
+Value URIErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *obj)
@@ -327,20 +327,22 @@ void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *ob
Value ErrorPrototype::method_toString(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Object *o = ctx->thisObject.asObject();
if (!o)
ctx->throwTypeError();
- Value name = o->get(ctx->engine->newString(QString::fromLatin1("name")));
+ ScopedValue name(scope, o->get(ctx->engine->newString(QString::fromLatin1("name"))));
QString qname;
- if (name.isUndefined())
+ if (name->isUndefined())
qname = QString::fromLatin1("Error");
else
qname = __qmljs_to_string(name, ctx).stringValue()->toQString();
- Value message = o->get(ctx->engine->newString(QString::fromLatin1("message")));
+ ScopedValue message(scope, o->get(ctx->engine->newString(QString::fromLatin1("message"))));
QString qmessage;
- if (!message.isUndefined())
+ if (!message->isUndefined())
qmessage = __qmljs_to_string(message, ctx).stringValue()->toQString();
QString str;
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index f8aeae603c..1d82bb7ba2 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -114,8 +114,8 @@ struct ErrorCtor: FunctionObject
ErrorCtor(ExecutionContext *scope);
ErrorCtor(ExecutionContext *scope, String *name);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -125,7 +125,7 @@ struct EvalErrorCtor: ErrorCtor
{
EvalErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -135,7 +135,7 @@ struct RangeErrorCtor: ErrorCtor
{
RangeErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -145,7 +145,7 @@ struct ReferenceErrorCtor: ErrorCtor
{
ReferenceErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -155,7 +155,7 @@ struct SyntaxErrorCtor: ErrorCtor
{
SyntaxErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -165,7 +165,7 @@ struct TypeErrorCtor: ErrorCtor
{
TypeErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -175,7 +175,7 @@ struct URIErrorCtor: ErrorCtor
{
URIErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index e989d31c1b..9907f3e2ba 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -54,21 +54,14 @@ using namespace QV4;
Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
Value (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize)
: name(0)
- , compiledFunction(0)
- , compilationUnit(0)
- , code(0)
+ , compiledFunction(function)
+ , compilationUnit(unit)
+ , codePtr(codePtr)
, codeData(0)
- , codeSize(0)
+ , codeSize(_codeSize)
{
- Q_ASSERT(!compilationUnit);
- compilationUnit = unit;
- compiledFunction = function;
-
name = compilationUnit->runtimeStrings[compiledFunction->nameIndex];
- code = codePtr;
- codeSize = _codeSize;
-
formals.resize(compiledFunction->nFormals);
const quint32 *formalsIndices = compiledFunction->formalsTable();
for (int i = 0; i < compiledFunction->nFormals; ++i)
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 735dc558e1..1fc40d7209 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -49,6 +49,7 @@
#include "qv4value_def_p.h"
#include <private/qv4compileddata_p.h>
+#include <private/qv4engine_p.h>
QT_BEGIN_NAMESPACE
@@ -84,7 +85,17 @@ struct Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- Value (*code)(ExecutionContext *, const uchar *);
+ inline Value code(ExecutionContext *ctx, const uchar *data) {
+ Value *stack = ctx->engine->jsStackTop;
+ try {
+ return codePtr(ctx, data);
+ } catch (...) {
+ ctx->engine->jsStackTop = stack;
+ throw;
+ }
+ }
+
+ Value (*codePtr)(ExecutionContext *, const uchar *);
const uchar *codeData;
quint32 codeSize;
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 925aadcdf1..252481b7f1 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -48,6 +48,7 @@
#include "qv4mm_p.h"
#include "qv4exception_p.h"
#include "qv4arrayobject_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -122,8 +123,8 @@ FunctionObject::~FunctionObject()
Value FunctionObject::newInstance()
{
- CALLDATA(0);
- return construct(d);
+ ScopedCallData callData(engine(), 0);
+ return construct(callData);
}
bool FunctionObject::hasInstance(Managed *that, const Value &value)
@@ -151,7 +152,7 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value)
return false;
}
-Value FunctionObject::construct(Managed *that, const CallData &)
+Value FunctionObject::construct(Managed *that, CallData *)
{
FunctionObject *f = static_cast<FunctionObject *>(that);
ExecutionEngine *v4 = f->engine();
@@ -164,7 +165,7 @@ Value FunctionObject::construct(Managed *that, const CallData &)
return Value::fromObject(obj);
}
-Value FunctionObject::call(Managed *, const CallData &)
+Value FunctionObject::call(Managed *, CallData *)
{
return Value::undefinedValue();
}
@@ -203,7 +204,7 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope)
}
// 15.3.2
-Value FunctionCtor::construct(Managed *that, const CallData &d)
+Value FunctionCtor::construct(Managed *that, CallData *callData)
{
FunctionCtor *f = static_cast<FunctionCtor *>(that);
MemoryManager::GCBlocker gcBlocker(f->engine()->memoryManager);
@@ -211,13 +212,13 @@ Value FunctionCtor::construct(Managed *that, const CallData &d)
ExecutionContext *ctx = f->engine()->current;
QString arguments;
QString body;
- if (d.argc > 0) {
- for (uint i = 0; i < d.argc - 1; ++i) {
+ if (callData->argc > 0) {
+ for (uint i = 0; i < callData->argc - 1; ++i) {
if (i)
arguments += QLatin1String(", ");
- arguments += d.args[i].toString(ctx)->toQString();
+ arguments += callData->args[i].toString(ctx)->toQString();
}
- body = d.args[d.argc - 1].toString(ctx)->toQString();
+ body = callData->args[callData->argc - 1].toString(ctx)->toQString();
}
QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
@@ -252,9 +253,9 @@ Value FunctionCtor::construct(Managed *that, const CallData &d)
}
// 15.3.1: This is equivalent to new Function(...)
-Value FunctionCtor::call(Managed *that, const CallData &d)
+Value FunctionCtor::call(Managed *that, CallData *callData)
{
- return construct(that, d);
+ return construct(that, callData);
}
FunctionPrototype::FunctionPrototype(InternalClass *ic)
@@ -307,23 +308,23 @@ Value FunctionPrototype::method_apply(SimpleCallContext *ctx)
len = ArrayPrototype::getLength(ctx, arr);
}
- CALLDATA(len);
+ ScopedCallData callData(ctx->engine, len);
if (len) {
if (arr->protoHasArray() || arr->hasAccessorProperty) {
for (quint32 i = 0; i < len; ++i)
- d.args[i] = arr->getIndexed(i);
+ callData->args[i] = arr->getIndexed(i);
} else {
int alen = qMin(len, arr->arrayDataLen);
for (quint32 i = 0; i < alen; ++i)
- d.args[i] = arr->arrayData[i].value;
+ callData->args[i] = arr->arrayData[i].value;
for (quint32 i = alen; i < len; ++i)
- d.args[i] = Value::undefinedValue();
+ callData->args[i] = Value::undefinedValue();
}
}
- d.thisObject = thisArg;
- return o->call(d);
+ callData->thisObject = thisArg;
+ return o->call(callData);
}
Value FunctionPrototype::method_call(SimpleCallContext *ctx)
@@ -334,12 +335,12 @@ Value FunctionPrototype::method_call(SimpleCallContext *ctx)
if (!o)
ctx->throwTypeError();
- CALLDATA(ctx->argumentCount ? ctx->argumentCount - 1 : 0);
+ ScopedCallData callData(ctx->engine, ctx->argumentCount ? ctx->argumentCount - 1 : 0);
if (ctx->argumentCount)
qCopy(ctx->arguments + 1,
- ctx->arguments + ctx->argumentCount, d.args);
- d.thisObject = thisArg;
- return o->call(d);
+ ctx->arguments + ctx->argumentCount, callData->args);
+ callData->thisObject = thisArg;
+ return o->call(callData);
}
Value FunctionPrototype::method_bind(SimpleCallContext *ctx)
@@ -373,8 +374,8 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
vtbl = &static_vtbl;
this->function = function;
this->function->compilationUnit->ref();
- assert(function);
- assert(function->code);
+ Q_ASSERT(function);
+ Q_ASSERT(function->codePtr);
// global function
if (!scope)
@@ -400,9 +401,10 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
}
}
-Value ScriptFunction::construct(Managed *that, const CallData &d)
+Value ScriptFunction::construct(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
ExecutionEngine *v4 = f->engine();
InternalClass *ic = v4->objectClass;
@@ -412,9 +414,8 @@ Value ScriptFunction::construct(Managed *that, const CallData &d)
Object *obj = v4->newObject(ic);
ExecutionContext *context = v4->current;
- CallData dd = d;
- dd.thisObject = Value::fromObject(obj);
- ExecutionContext *ctx = context->newCallContext(f, dd);
+ callData->thisObject = Value::fromObject(obj);
+ ExecutionContext *ctx = context->newCallContext(f, callData);
Value result;
try {
@@ -425,23 +426,25 @@ Value ScriptFunction::construct(Managed *that, const CallData &d)
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
if (result.isObject())
return result;
return Value::fromObject(obj);
}
-Value ScriptFunction::call(Managed *that, const CallData &d)
+Value ScriptFunction::call(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
void *stackSpace;
ExecutionContext *context = f->engine()->current;
- ExecutionContext *ctx = context->newCallContext(f, d);
+ CallContext *ctx = context->newCallContext(f, callData);
- if (!f->strictMode && !d.thisObject.isObject()) {
- if (d.thisObject.isNullOrUndefined()) {
+ if (!f->strictMode && !callData->thisObject.isObject()) {
+ if (callData->thisObject.isNullOrUndefined()) {
ctx->thisObject = Value::fromObject(f->engine()->globalObject);
} else {
- ctx->thisObject = Value::fromObject(d.thisObject.toObject(context));
+ ctx->thisObject = Value::fromObject(callData->thisObject.toObject(context));
}
}
@@ -453,6 +456,7 @@ Value ScriptFunction::call(Managed *that, const CallData &d)
throw;
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
return result;
}
@@ -464,8 +468,8 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
vtbl = &static_vtbl;
this->function = function;
this->function->compilationUnit->ref();
- assert(function);
- assert(function->code);
+ Q_ASSERT(function);
+ Q_ASSERT(function->codePtr);
// global function
if (!scope)
@@ -491,9 +495,10 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
}
}
-Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
+Value SimpleScriptFunction::construct(Managed *that, CallData *callData)
{
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
ExecutionEngine *v4 = f->engine();
InternalClass *ic = v4->objectClass;
@@ -504,9 +509,8 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
ExecutionContext *context = v4->current;
void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
- CallData dd = d;
- dd.thisObject = Value::fromObject(obj);
- ExecutionContext *ctx = context->newCallContext(stackSpace, f, dd);
+ callData->thisObject = Value::fromObject(obj);
+ ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData);
Value result;
try {
@@ -517,23 +521,25 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
if (result.isObject())
return result;
return Value::fromObject(obj);
}
-Value SimpleScriptFunction::call(Managed *that, const CallData &d)
+Value SimpleScriptFunction::call(Managed *that, CallData *callData)
{
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
ExecutionContext *context = f->engine()->current;
- ExecutionContext *ctx = context->newCallContext(stackSpace, f, d);
+ ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData);
- if (!f->strictMode && !d.thisObject.isObject()) {
- if (d.thisObject.isNullOrUndefined()) {
+ if (!f->strictMode && !callData->thisObject.isObject()) {
+ if (callData->thisObject.isNullOrUndefined()) {
ctx->thisObject = Value::fromObject(f->engine()->globalObject);
} else {
- ctx->thisObject = Value::fromObject(d.thisObject.toObject(context));
+ ctx->thisObject = Value::fromObject(callData->thisObject.toObject(context));
}
}
@@ -545,6 +551,7 @@ Value SimpleScriptFunction::call(Managed *that, const CallData &d)
throw;
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
return result;
}
@@ -561,13 +568,13 @@ BuiltinFunctionOld::BuiltinFunctionOld(ExecutionContext *scope, String *name, Va
isBuiltinFunction = true;
}
-Value BuiltinFunctionOld::construct(Managed *f, const CallData &d)
+Value BuiltinFunctionOld::construct(Managed *f, CallData *)
{
f->engine()->current->throwTypeError();
return Value::undefinedValue();
}
-Value BuiltinFunctionOld::call(Managed *that, const CallData &d)
+Value BuiltinFunctionOld::call(Managed *that, CallData *callData)
{
BuiltinFunctionOld *f = static_cast<BuiltinFunctionOld *>(that);
ExecutionEngine *v4 = f->engine();
@@ -576,9 +583,10 @@ Value BuiltinFunctionOld::call(Managed *that, const CallData &d)
SimpleCallContext ctx;
ctx.initSimpleCallContext(f->scope->engine);
ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
- ctx.thisObject = d.thisObject;
- ctx.arguments = d.args;
- ctx.argumentCount = d.argc;
+ ctx.thisObject = callData->thisObject;
+ // ### const_cast
+ ctx.arguments = const_cast<Value *>(callData->args);
+ ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);
Value result;
@@ -593,7 +601,7 @@ Value BuiltinFunctionOld::call(Managed *that, const CallData &d)
return result;
}
-Value IndexedBuiltinFunction::call(Managed *that, const CallData &d)
+Value IndexedBuiltinFunction::call(Managed *that, CallData *callData)
{
IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->engine();
@@ -602,9 +610,10 @@ Value IndexedBuiltinFunction::call(Managed *that, const CallData &d)
SimpleCallContext ctx;
ctx.initSimpleCallContext(f->scope->engine);
ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
- ctx.thisObject = d.thisObject;
- ctx.arguments = d.args;
- ctx.argumentCount = d.argc;
+ ctx.thisObject = callData->thisObject;
+ // ### const_cast
+ ctx.arguments = const_cast<Value *>(callData->args);
+ ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);
Value result;
@@ -647,24 +656,24 @@ void BoundFunction::destroy(Managed *that)
static_cast<BoundFunction *>(that)->~BoundFunction();
}
-Value BoundFunction::call(Managed *that, const CallData &dd)
+Value BoundFunction::call(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- CALLDATA(f->boundArgs.size() + dd.argc);
- d.thisObject = f->boundThis;
- memcpy(d.args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
- memcpy(d.args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value));
- return f->target->call(d);
+ ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd->argc);
+ callData->thisObject = f->boundThis;
+ memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
+ return f->target->call(callData);
}
-Value BoundFunction::construct(Managed *that, const CallData &dd)
+Value BoundFunction::construct(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- CALLDATA(f->boundArgs.size() + dd.argc);
- memcpy(d.args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
- memcpy(d.args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value));
- return f->target->construct(d);
+ ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd->argc);
+ memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
+ return f->target->construct(callData);
}
bool BoundFunction::hasInstance(Managed *that, const Value &value)
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 4d4174d053..d694d28462 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -117,13 +117,13 @@ struct Q_QML_EXPORT FunctionObject: Object {
Value newInstance();
- static Value construct(Managed *that, const CallData &);
- static Value call(Managed *that, const CallData &d);
- inline Value construct(const CallData &d) {
- return vtbl->construct(this, d);
+ static Value construct(Managed *that, CallData *);
+ static Value call(Managed *that, CallData *d);
+ inline Value construct(CallData *callData) {
+ return vtbl->construct(this, callData);
}
- inline Value call(const CallData &d) {
- return vtbl->call(this, d);
+ inline Value call(CallData *callData) {
+ return vtbl->call(this, callData);
}
static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function);
@@ -142,8 +142,8 @@ struct FunctionCtor: FunctionObject
{
FunctionCtor(ExecutionContext *scope);
- static Value construct(Managed *that, const CallData &);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *that, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -165,8 +165,8 @@ struct BuiltinFunctionOld: FunctionObject {
BuiltinFunctionOld(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *));
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -188,21 +188,21 @@ struct IndexedBuiltinFunction: FunctionObject
isBuiltinFunction = true;
}
- static Value construct(Managed *m, const CallData &)
+ static Value construct(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
return Value::undefinedValue();
}
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *callData);
};
struct ScriptFunction: FunctionObject {
ScriptFunction(ExecutionContext *scope, Function *function);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -211,8 +211,8 @@ protected:
struct SimpleScriptFunction: FunctionObject {
SimpleScriptFunction(ExecutionContext *scope, Function *function);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -227,8 +227,8 @@ struct BoundFunction: FunctionObject {
~BoundFunction() {}
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *d);
+ static Value call(Managed *that, CallData *dd);
static const ManagedVTable static_vtbl;
static void destroy(Managed *);
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 3b06a6d884..9764a7930f 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -47,6 +47,7 @@
#include "qv4debugging_p.h"
#include "qv4script_p.h"
#include "qv4exception_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -390,9 +391,9 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
if (strictMode) {
FunctionObject *e = FunctionObject::creatScriptFunction(ctx, function);
- CALLDATA(0);
- d.thisObject = ctx->thisObject;
- return e->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = ctx->thisObject;
+ return e->call(callData);
}
ExecutionContext::EvalCode evalCode;
@@ -438,10 +439,11 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
}
-Value EvalFunction::call(Managed *that, const CallData &d)
+Value EvalFunction::call(Managed *that, CallData *callData)
{
// indirect call
- return static_cast<EvalFunction *>(that)->evalCall(d.thisObject, d.args, d.argc, false);
+ // ### const_cast
+ return static_cast<EvalFunction *>(that)->evalCall(callData->thisObject, const_cast<Value *>(callData->args), callData->argc, false);
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 4ac531c27b..b777bf8915 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -55,7 +55,7 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
Value evalCall(Value thisObject, Value *args, int argc, bool directCall);
using Managed::construct;
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 5d8077bfdc..08f48c36a4 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -114,7 +114,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const Identifier *identifi
{
if (!d)
return 0;
- assert(d->entries);
+ Q_ASSERT(d->entries);
uint idx = identifier->hashValue % d->alloc;
while (1) {
@@ -131,7 +131,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
{
if (!d)
return 0;
- assert(d->entries);
+ Q_ASSERT(d->entries);
uint hash = String::createHashValue(str.constData(), str.length());
uint idx = hash % d->alloc;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 9068d573f6..647cc7d2cb 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4include_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtQml/qjsengine.h>
#include <QtNetwork/qnetworkrequest.h>
@@ -104,10 +105,10 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
QV4::ExecutionContext *ctx = f->engine()->current;
try {
- CALLDATA(1);
- d.thisObject = QV4::Value::fromObject(f->engine()->globalObject);
- d.args[0] = status;
- f->call(d);
+ QV4::ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = QV4::Value::fromObject(f->engine()->globalObject);
+ callData->args[0] = status;
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 9c98d78743..ef1f500580 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -44,6 +44,7 @@
#include <qv4stringobject_p.h>
#include <qv4booleanobject_p.h>
#include <qv4objectiterator_p.h>
+#include <qv4scopedvalue_p.h>
#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -702,10 +703,10 @@ QString Stringify::Str(const QString &key, Value value)
if (Object *o = value.asObject()) {
FunctionObject *toJSON = o->get(ctx->engine->newString(QStringLiteral("toJSON"))).asFunctionObject();
if (toJSON) {
- CALLDATA(1);
- d.thisObject = value;
- d.args[0] = Value::fromString(ctx, key);
- value = toJSON->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = value;
+ callData->args[0] = Value::fromString(ctx, key);
+ value = toJSON->call(callData);
}
}
@@ -713,11 +714,11 @@ QString Stringify::Str(const QString &key, Value value)
Object *holder = ctx->engine->newObject();
Value holderValue = Value::fromObject(holder);
holder->put(ctx, QString(), value);
- CALLDATA(2);
- d.args[0] = Value::fromString(ctx, key);
- d.args[1] = value;
- d.thisObject = holderValue;
- value = replacerFunction->call(d);
+ ScopedCallData callData(ctx->engine, 2);
+ callData->args[0] = Value::fromString(ctx, key);
+ callData->args[1] = value;
+ callData->thisObject = holderValue;
+ value = replacerFunction->call(callData);
}
if (Object *o = value.asObject()) {
@@ -885,6 +886,8 @@ Value JsonObject::method_parse(SimpleCallContext *ctx)
Value JsonObject::method_stringify(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Stringify stringify(ctx);
Object *o = ctx->argument(1).asObject();
@@ -892,12 +895,13 @@ Value JsonObject::method_stringify(SimpleCallContext *ctx)
stringify.replacerFunction = o->asFunctionObject();
if (o->isArrayObject()) {
uint arrayLen = o->arrayLength();
+ ScopedValue v(scope);
for (uint i = 0; i < arrayLen; ++i) {
- Value v = o->getIndexed(i);
- if (v.asNumberObject() || v.asStringObject() || v.isNumber())
+ v = o->getIndexed(i);
+ if (v->asNumberObject() || v->asStringObject() || v->isNumber())
v = __qmljs_to_string(v, ctx);
- if (v.isString()) {
- String *s = v.stringValue();
+ if (v->isString()) {
+ String *s = v->stringValue();
if (!stringify.propertyList.contains(s))
stringify.propertyList.append(s);
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index e66055653e..2cffa55642 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4lookup_p.h"
#include "qv4functionobject_p.h"
+#include "qv4scopedvalue_p.h"
QT_BEGIN_NAMESPACE
@@ -202,9 +203,9 @@ void Lookup::getterAccessor0(Lookup *l, Value *result, const Value &object)
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -225,9 +226,9 @@ void Lookup::getterAccessor1(Lookup *l, Value *result, const Value &object)
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -251,9 +252,9 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object)
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -306,9 +307,9 @@ void Lookup::primitiveGetterAccessor0(Lookup *l, Value *result, const Value &obj
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -330,9 +331,9 @@ void Lookup::primitiveGetterAccessor1(Lookup *l, Value *result, const Value &obj
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -434,9 +435,9 @@ void Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx, Value *resu
if (!getter) {
*result = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- *result = getter->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ *result = getter->call(callData);
}
return;
}
@@ -453,9 +454,9 @@ void Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *resu
if (!getter) {
*result = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- *result = getter->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ *result = getter->call(callData);
}
return;
}
@@ -475,9 +476,9 @@ void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *resu
if (!getter) {
*result = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- *result = getter->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ *result = getter->call(callData);
}
return;
}
@@ -491,7 +492,7 @@ void Lookup::setterGeneric(Lookup *l, const Value &object, const Value &value)
{
Object *o = object.asObject();
if (!o) {
- o = __qmljs_convert_to_object(l->name->engine()->current, object);
+ o = __qmljs_convert_to_object(l->name->engine()->current, ValueRef::fromRawValue(&object));
o->put(l->name, value);
return;
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 955d12a3d0..62491ba7e5 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -176,12 +176,12 @@ bool Managed::hasInstance(Managed *m, const Value &)
m->engine()->current->throwTypeError();
}
-Value Managed::construct(Managed *m, const CallData &)
+Value Managed::construct(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
}
-Value Managed::call(Managed *m, const CallData &)
+Value Managed::call(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index b77b1cd638..50325478f5 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -76,28 +76,23 @@ struct GCDeletable
struct CallData
{
- Value thisObject;
- Value *args;
+ // below is to be compatible with Value. Initialize tag to 0
+#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
+ uint tag;
+#endif
int argc;
-};
-
-#ifdef QT_NO_DEBUG
-#define CALLDATA(argc_) \
- QV4::CallData d; \
- d.argc = argc_; \
- d.args = (QV4::Value *)alloca(qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value))
-#else
-#define CALLDATA(argc_) \
- QV4::CallData d; \
- d.argc = argc_; \
- d.args = (QV4::Value *)alloca(qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value)); \
- for (int iii = 0; iii < qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount); ++iii) d.args[iii] = QV4::Value::undefinedValue()
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint tag;
#endif
+ Value thisObject;
+ Value args[1];
+};
+
struct ManagedVTable
{
- Value (*call)(Managed *, const CallData &data);
- Value (*construct)(Managed *, const CallData &data);
+ Value (*call)(Managed *, CallData *data);
+ Value (*construct)(Managed *, CallData *data);
void (*markObjects)(Managed *);
void (*destroy)(Managed *);
void (*collectDeletables)(Managed *, GCDeletable **deletable);
@@ -257,8 +252,8 @@ public:
inline bool hasInstance(const Value &v) {
return vtbl->hasInstance(this, v);
}
- Value construct(const CallData &d);
- Value call(const CallData &d);
+ Value construct(CallData *d);
+ Value call(CallData *d);
Value get(String *name, bool *hasProperty = 0);
Value getIndexed(uint index, bool *hasProperty = 0);
void put(String *name, const Value &value)
@@ -286,8 +281,8 @@ public:
static void destroy(Managed *that) { that->_data = 0; }
static bool hasInstance(Managed *that, const Value &value);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *m, const CallData &);
+ static Value construct(Managed *m, CallData *d);
+ static Value call(Managed *m, CallData *);
static void getLookup(Managed *m, Lookup *, Value *);
static void setLookup(Managed *m, Lookup *l, const Value &v);
static bool isEqualTo(Managed *m, Managed *other);
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 095d27e1c0..874c349c42 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -293,6 +293,7 @@ void MemoryManager::mark()
#endif // COMPILER
collectFromStack();
+ collectFromJSStack();
// Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
// keeps all of its children alive in JavaScript.
@@ -602,4 +603,16 @@ void MemoryManager::collectFromStack() const
}
}
+void MemoryManager::collectFromJSStack() const
+{
+ Value *v = engine()->jsStackBase;
+ Value *top = engine()->jsStackTop;
+ while (v < top) {
+ Managed *m = v->asManaged();
+ if (m && m->inUse)
+ // Skip pointers to already freed objects, they are bogus as well
+ m->mark();
+ ++v;
+ }
+}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h
index f72d23dc9a..abbc0a7b4e 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/jsruntime/qv4mm_p.h
@@ -44,6 +44,7 @@
#include "qv4global_p.h"
#include "qv4context_p.h"
+#include "qv4value_p.h"
#include <QScopedPointer>
@@ -129,6 +130,7 @@ protected:
private:
void collectFromStack() const;
+ void collectFromJSStack() const;
void mark();
std::size_t sweep(bool lastSweep = false);
std::size_t sweep(char *chunkStart, std::size_t chunkSize, size_t size, GCDeletable **deletable);
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 88c61489db..ffcbca2ce5 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -56,15 +56,15 @@ NumberCtor::NumberCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value NumberCtor::construct(Managed *m, const CallData &d)
+Value NumberCtor::construct(Managed *m, CallData *callData)
{
- double dbl = d.argc ? d.args[0].toNumber() : 0.;
+ double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Value::fromObject(m->engine()->newNumberObject(Value::fromDouble(dbl)));
}
-Value NumberCtor::call(Managed *, const CallData &d)
+Value NumberCtor::call(Managed *, CallData *callData)
{
- double dbl = d.argc ? d.args[0].toNumber() : 0.;
+ double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Value::fromDouble(dbl);
}
@@ -225,7 +225,9 @@ Value NumberPrototype::method_toExponential(SimpleCallContext *ctx)
Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
{
- Value v = thisNumberValue(ctx);
+ ValueScope scope(ctx);
+
+ ScopedValue v(scope, thisNumberValue(ctx));
Value prec = ctx->argument(0);
if (prec.isUndefined())
@@ -239,7 +241,7 @@ Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
char str[100];
double_conversion::StringBuilder builder(str, sizeof(str));
- double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v.asDouble(), precision, &builder);
+ double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v->asDouble(), precision, &builder);
QString result = QString::fromLatin1(builder.Finalize());
return Value::fromString(ctx, result);
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 096b4b3d9f..a0c2a65e80 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -53,8 +53,8 @@ struct NumberCtor: FunctionObject
{
NumberCtor(ExecutionContext *scope);
- static Value construct(Managed *that, const CallData &d);
- static Value call(Managed *, const CallData &d);
+ static Value construct(Managed *that, CallData *callData);
+ static Value call(Managed *, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index c3c444b7b9..14584da46d 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -47,6 +47,7 @@
#include "qv4argumentsobject_p.h"
#include "qv4mm_p.h"
#include "qv4lookup_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -134,19 +135,19 @@ Value Object::getValue(const Value &thisObject, const Property *p, PropertyAttri
if (!getter)
return Value::undefinedValue();
- CALLDATA(0);
- d.thisObject = thisObject;
- return getter->call(d);
+ ScopedCallData callData(getter->engine(), 0);
+ callData->thisObject = thisObject;
+ return getter->call(callData);
}
void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value)
{
if (attrs.isAccessor()) {
if (pd->set) {
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(this);
- pd->set->call(d);
+ ScopedCallData callData(pd->set->engine(), 1);
+ callData->args[0] = value;
+ callData->thisObject = Value::fromObject(this);
+ pd->set->call(callData);
return;
}
goto reject;
@@ -164,50 +165,54 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
}
-void Object::inplaceBinOp(ExecutionContext *, BinOp op, String *name, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, String *name, const ValueRef rhs)
{
- Value v = get(name);
- Value result;
- op(&result, v, rhs);
+ ValueScope scope(ctx);
+ ScopedValue v(scope, get(name));
+ ScopedValue result(scope);
+ op(result, v, rhs);
put(name, result);
}
-void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, const Value &index, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, const ValueRef index, const ValueRef rhs)
{
- uint idx = index.asArrayIndex();
+ ValueScope scope(ctx);
+ uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
bool hasProperty = false;
- Value v = getIndexed(idx, &hasProperty);
- Value result;
- op(&result, v, rhs);
+ ScopedValue v(scope, getIndexed(idx, &hasProperty));
+ ScopedValue result(scope);
+ op(result, v, rhs);
putIndexed(idx, result);
return;
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
assert(name);
inplaceBinOp(ctx, op, name, rhs);
}
-void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const ValueRef rhs)
{
- Value v = get(name);
- Value result;
- op(ctx, &result, v, rhs);
+ ValueScope scope(ctx);
+ ScopedValue v(scope, get(name));
+ ScopedValue result(scope);
+ op(ctx, result, v, rhs);
put(name, result);
}
-void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const Value &index, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const ValueRef index, const ValueRef rhs)
{
- uint idx = index.asArrayIndex();
+ ValueScope scope(ctx);
+ uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
bool hasProperty = false;
- Value v = getIndexed(idx, &hasProperty);
- Value result;
- op(ctx, &result, v, rhs);
+ ScopedValue v(scope, getIndexed(idx, &hasProperty));
+ ScopedValue result(scope);
+ op(ctx, result, v, rhs);
putIndexed(idx, result);
return;
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
assert(name);
inplaceBinOp(ctx, op, name, rhs);
}
@@ -773,10 +778,10 @@ void Object::internalPut(String *name, const Value &value)
if (pd && attrs.isAccessor()) {
assert(pd->setter() != 0);
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(this);
- pd->setter()->call(d);
+ ScopedCallData callData(engine(), 1);
+ callData->args[0] = value;
+ callData->thisObject = Value::fromObject(this);
+ pd->setter()->call(callData);
return;
}
@@ -851,10 +856,10 @@ void Object::internalPutIndexed(uint index, const Value &value)
if (pd && attrs.isAccessor()) {
assert(pd->setter() != 0);
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(this);
- pd->setter()->call(d);
+ ScopedCallData callData(engine(), 1);
+ callData->args[0] = value;
+ callData->thisObject = Value::fromObject(this);
+ pd->setter()->call(callData);
return;
}
@@ -1132,18 +1137,21 @@ void Object::copyArrayData(Object *other)
Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
{
+ ValueScope scope(engine());
+ ScopedValue value(scope);
+
if (o->protoHasArray() || o->arrayAttributes) {
// lets be safe and slow
for (uint i = fromIndex; i < endIndex; ++i) {
bool exists;
- Value value = o->getIndexed(i, &exists);
- if (exists && __qmljs_strict_equal(value, v))
+ value = o->getIndexed(i, &exists);
+ if (exists && __qmljs_strict_equal(value, ValueRef(&v)))
return Value::fromDouble(i);
}
} else if (sparseArray) {
for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
- Value value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
- if (__qmljs_strict_equal(value, v))
+ value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
+ if (__qmljs_strict_equal(value, ValueRef(&v)))
return Value::fromDouble(n->key());
}
} else {
@@ -1154,8 +1162,8 @@ Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionCont
pd += fromIndex;
while (pd < end) {
if (!arrayAttributes || !arrayAttributes[pd - arrayData].isGeneric()) {
- Value value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
- if (__qmljs_strict_equal(value, v))
+ value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
+ if (__qmljs_strict_equal(value, ValueRef(&v)))
return Value::fromDouble(pd - arrayData);
}
++pd;
@@ -1246,6 +1254,9 @@ void Object::arraySort(ExecutionContext *context, Object *thisObject, const Valu
}
}
+ if (!(comparefn.isUndefined() || comparefn.asObject()))
+ context->throwTypeError();
+
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Property *begin = arrayData;
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 995749ff74..c6329b9665 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -156,10 +156,10 @@ struct Q_QML_EXPORT Object: Managed {
void putValue(Property *pd, PropertyAttributes attrs, const Value &value);
- void inplaceBinOp(ExecutionContext *, BinOp op, String *name, const Value &rhs);
- void inplaceBinOp(ExecutionContext *ctx, BinOp op, const Value &index, const Value &rhs);
- void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const Value &rhs);
- void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const Value &index, const Value &rhs);
+ void inplaceBinOp(ExecutionContext *, BinOp op, String *name, const ValueRef rhs);
+ void inplaceBinOp(ExecutionContext *ctx, BinOp op, const ValueRef index, const ValueRef rhs);
+ void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const ValueRef rhs);
+ void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const ValueRef index, const ValueRef rhs);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
void defineDefaultProperty(String *name, Value value);
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index fbf86645e2..2f8f6375f0 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -42,6 +42,7 @@
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -78,25 +79,25 @@ ObjectCtor::ObjectCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ObjectCtor::construct(Managed *that, const CallData &d)
+Value ObjectCtor::construct(Managed *that, CallData *callData)
{
ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
ExecutionEngine *v4 = that->engine();
- if (!d.argc || d.args[0].isUndefined() || d.args[0].isNull()) {
+ if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
Object *obj = v4->newObject();
Value proto = ctor->get(v4->id_prototype);
if (proto.isObject())
obj->setPrototype(proto.objectValue());
return Value::fromObject(obj);
}
- return __qmljs_to_object(v4->current, d.args[0]);
+ return __qmljs_to_object(v4->current, ValueRef(&callData->args[0]));
}
-Value ObjectCtor::call(Managed *m, const CallData &d)
+Value ObjectCtor::call(Managed *m, CallData *callData)
{
- if (!d.argc || d.args[0].isUndefined() || d.args[0].isNull())
+ if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return Value::fromObject(m->engine()->newObject());
- return __qmljs_to_object(m->engine()->current, d.args[0]);
+ return __qmljs_to_object(m->engine()->current, ValueRef(&callData->args[0]));
}
void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -372,7 +373,7 @@ Value ObjectPrototype::method_toString(SimpleCallContext *ctx)
} else if (ctx->thisObject.isNull()) {
return Value::fromString(ctx, QStringLiteral("[object Null]"));
} else {
- Value obj = __qmljs_to_object(ctx, ctx->thisObject);
+ Value obj = __qmljs_to_object(ctx, ValueRef(&ctx->thisObject));
QString className = obj.objectValue()->className();
return Value::fromString(ctx, QString::fromUtf8("[object %1]").arg(className));
}
@@ -385,9 +386,9 @@ Value ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx)
FunctionObject *f = ts.asFunctionObject();
if (!f)
ctx->throwTypeError();
- CALLDATA(0);
- d.thisObject = Value::fromObject(o);
- return f->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::fromObject(o);
+ return f->call(callData);
}
Value ObjectPrototype::method_valueOf(SimpleCallContext *ctx)
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index be51c41580..33a115f203 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -53,8 +53,8 @@ struct ObjectCtor: FunctionObject
{
ObjectCtor(ExecutionContext *scope);
- static Value construct(Managed *that, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *that, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 9e80c82165..1e868ef3fe 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -62,6 +62,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4scopedvalue_p.h>
#include <QtQml/qjsvalue.h>
#include <QtCore/qjsonarray.h>
@@ -700,19 +701,19 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ExecutionEngine *v4 = f->internalClass->engine;
QV4::ExecutionContext *ctx = v4->current;
- CALLDATA(argCount);
- d.thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value();
+ QV4::ScopedCallData callData(v4, argCount);
+ callData->thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
- d.args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ callData->args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
} else {
- d.args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ callData->args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
}
}
try {
- f->call(d);
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
@@ -739,14 +740,15 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
return;
}
- QV4::Value function = *reinterpret_cast<QV4::Value*>(metaArgs[1]);
- QV4::Value thisObject = *reinterpret_cast<QV4::Value*>(metaArgs[2]);
+ QV4::ValueScope scope(v4);
+ QV4::ScopedValue function(scope, *reinterpret_cast<QV4::Value*>(metaArgs[1]));
+ QV4::ScopedValue thisObject(scope, *reinterpret_cast<QV4::Value*>(metaArgs[2]));
QObject *receiverToDisconnect = reinterpret_cast<QObject*>(metaArgs[3]);
int slotIndexToDisconnect = *reinterpret_cast<int*>(metaArgs[4]);
if (slotIndexToDisconnect != -1) {
// This is a QObject function wrapper
- if (connection->thisObject.isEmpty() == thisObject.isEmpty() &&
+ if (connection->thisObject.isEmpty() == thisObject->isEmpty() &&
(connection->thisObject.isEmpty() || __qmljs_strict_equal(connection->thisObject, thisObject))) {
QPair<QObject *, int> connectedFunctionData = extractQtMethod(connection->function.value().asFunctionObject());
@@ -759,7 +761,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
} else {
// This is a normal JS function
if (__qmljs_strict_equal(connection->function, function) &&
- connection->thisObject.isEmpty() == thisObject.isEmpty() &&
+ connection->thisObject.isEmpty() == thisObject->isEmpty() &&
(connection->thisObject.isEmpty() || __qmljs_strict_equal(connection->thisObject, thisObject))) {
*ret = true;
return;
@@ -1009,13 +1011,13 @@ private:
namespace {
struct CallArgs
{
- CallArgs(int length, QV4::Value *args) : _length(length), _args(args) {}
+ CallArgs(int length, const QV4::Value *args) : _length(length), _args(args) {}
int Length() const { return _length; }
QV4::Value operator[](int idx) { return _args[idx]; }
private:
int _length;
- QV4::Value *_args;
+ const QV4::Value *_args;
};
}
@@ -1667,7 +1669,7 @@ QV4::Value QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
return QV4::Value::fromString(ctx, result);
}
-QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc)
+QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
{
if (!m_object)
return QV4::Value::undefinedValue();
@@ -1686,17 +1688,17 @@ QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args
return QV4::Value::undefinedValue();
}
-Value QObjectMethod::call(Managed *m, const CallData &d)
+Value QObjectMethod::call(Managed *m, CallData *callData)
{
QObjectMethod *This = static_cast<QObjectMethod*>(m);
- return This->callInternal(d);
+ return This->callInternal(callData);
}
-Value QObjectMethod::callInternal(const CallData &d)
+Value QObjectMethod::callInternal(CallData *callData)
{
ExecutionContext *context = engine()->current;
if (m_index == DestroyMethod)
- return method_destroy(context, d.args, d.argc);
+ return method_destroy(context, callData->args, callData->argc);
else if (m_index == ToStringMethod)
return method_toString(context);
@@ -1731,7 +1733,7 @@ Value QObjectMethod::callInternal(const CallData &d)
if (method.isV4Function()) {
QV4::Value rv = QV4::Value::undefinedValue();
- QQmlV4Function func(d.argc, d.args, &rv, m_qmlGlobal.value(),
+ QQmlV4Function func(callData->argc, callData->args, &rv, m_qmlGlobal.value(),
QmlContextWrapper::getContext(m_qmlGlobal.value()),
v8Engine);
QQmlV4Function *funcptr = &func;
@@ -1742,7 +1744,7 @@ Value QObjectMethod::callInternal(const CallData &d)
return rv;
}
- CallArgs callArgs(d.argc, d.args);
+ CallArgs callArgs(callData->argc, callData->args);
if (!method.isOverload()) {
return CallPrecise(object, method, v8Engine, callArgs);
} else {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 39af02f38b..3a48fee1ec 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -135,15 +135,15 @@ private:
QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const QV4::Value &qmlGlobal);
QV4::Value method_toString(QV4::ExecutionContext *ctx);
- QV4::Value method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc);
+ QV4::Value method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
QPointer<QObject> m_object;
int m_index;
QV4::PersistentValue m_qmlGlobal;
- static Value call(Managed *, const CallData &d);
+ static Value call(Managed *, CallData *callData);
- Value callInternal(const CallData &d);
+ Value callInternal(CallData *callData);
static void destroy(Managed *that)
{
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index c213c78aeb..448d10180c 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -45,6 +45,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -228,13 +229,15 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value RegExpCtor::construct(Managed *m, const CallData &d)
+Value RegExpCtor::construct(Managed *m, CallData *callData)
{
- Value r = d.argc > 0 ? d.args[0] : Value::undefinedValue();
- Value f = d.argc > 1 ? d.args[1] : Value::undefinedValue();
ExecutionContext *ctx = m->engine()->current;
- if (RegExpObject *re = r.as<RegExpObject>()) {
- if (!f.isUndefined())
+ ValueScope scope(ctx);
+
+ ScopedValue r(scope, callData->argc > 0 ? callData->args[0] : Value::undefinedValue());
+ ScopedValue f(scope, callData->argc > 1 ? callData->args[1] : Value::undefinedValue());
+ if (RegExpObject *re = r->as<RegExpObject>()) {
+ if (!f->isUndefined())
ctx->throwTypeError();
RegExpObject *o = ctx->engine->newRegExpObject(re->value, re->global);
@@ -242,15 +245,15 @@ Value RegExpCtor::construct(Managed *m, const CallData &d)
}
QString pattern;
- if (!r.isUndefined())
- pattern = r.toString(ctx)->toQString();
+ if (!r->isUndefined())
+ pattern = r->toString(ctx)->toQString();
bool global = false;
bool ignoreCase = false;
bool multiLine = false;
- if (!f.isUndefined()) {
+ if (!f->isUndefined()) {
f = __qmljs_to_string(f, ctx);
- QString str = f.stringValue()->toQString();
+ QString str = f->stringValue()->toQString();
for (int i = 0; i < str.length(); ++i) {
if (str.at(i) == QChar('g') && !global) {
global = true;
@@ -272,14 +275,14 @@ Value RegExpCtor::construct(Managed *m, const CallData &d)
return Value::fromObject(o);
}
-Value RegExpCtor::call(Managed *that, const CallData &d)
+Value RegExpCtor::call(Managed *that, CallData *callData)
{
- if (d.argc > 0 && d.args[0].as<RegExpObject>()) {
- if (d.argc == 1 || d.args[1].isUndefined())
- return d.args[0];
+ if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
+ if (callData->argc == 1 || callData->args[1].isUndefined())
+ return callData->args[0];
}
- return construct(that, d);
+ return construct(that, callData);
}
void RegExpPrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -295,13 +298,15 @@ void RegExpPrototype::init(ExecutionContext *ctx, const Value &ctor)
Value RegExpPrototype::method_exec(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
RegExpObject *r = ctx->thisObject.as<RegExpObject>();
if (!r)
ctx->throwTypeError();
- Value arg = ctx->argument(0);
+ ScopedValue arg(scope, ctx->argument(0));
arg = __qmljs_to_string(arg, ctx);
- QString s = arg.stringValue()->toQString();
+ QString s = arg->stringValue()->toQString();
int offset = r->global ? r->lastIndexProperty(ctx)->value.toInt32() : 0;
if (offset < 0 || offset > s.length()) {
@@ -358,10 +363,9 @@ Value RegExpPrototype::method_compile(SimpleCallContext *ctx)
if (!r)
ctx->throwTypeError();
- CallData d;
- d.args = ctx->arguments;
- d.argc = ctx->argumentCount;
- RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(d).as<RegExpObject>();
+ ScopedCallData callData(ctx->engine, ctx->argumentCount);
+ memcpy(callData->args, ctx->arguments, ctx->argumentCount*sizeof(Value));
+ RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>();
r->value = re->value;
r->global = re->global;
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 80868d90db..a17802e2ff 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -105,8 +105,8 @@ struct RegExpCtor: FunctionObject
{
RegExpCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 33521efb02..733f353330 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -51,6 +51,7 @@
#include "qv4function_p.h"
#include "qv4exception_p.h"
#include "private/qlocale_tools_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qnumeric.h>
@@ -119,17 +120,17 @@ void __qmljs_numberToString(QString *result, double num, int radix)
result->prepend(QLatin1Char('-'));
}
-void __qmljs_init_closure(ExecutionContext *ctx, Value *result, int functionId)
+void __qmljs_init_closure(ExecutionContext *ctx, ValueRef result, int functionId)
{
QV4::Function *clos = ctx->compilationUnit->runtimeFunctions[functionId];
assert(clos);
*result = Value::fromObject(FunctionObject::creatScriptFunction(ctx, clos));
}
-void __qmljs_delete_subscript(ExecutionContext *ctx, Value *result, const Value &base, const Value &index)
+void __qmljs_delete_subscript(ExecutionContext *ctx, ValueRef result, const ValueRef base, const ValueRef index)
{
- if (Object *o = base.asObject()) {
- uint n = index.asArrayIndex();
+ if (Object *o = base->asObject()) {
+ uint n = index->asArrayIndex();
if (n < UINT_MAX) {
Value res = Value::fromBoolean(o->deleteIndexedProperty(n));
if (result)
@@ -138,35 +139,37 @@ void __qmljs_delete_subscript(ExecutionContext *ctx, Value *result, const Value
}
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
__qmljs_delete_member(ctx, result, base, name);
}
-void __qmljs_delete_member(ExecutionContext *ctx, Value *result, const Value &base, String *name)
+void __qmljs_delete_member(ExecutionContext *ctx, ValueRef result, const ValueRef base, String *name)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
Value res = Value::fromBoolean(obj->deleteProperty(name));
if (result)
*result = res;
}
-void __qmljs_delete_name(ExecutionContext *ctx, Value *result, String *name)
+void __qmljs_delete_name(ExecutionContext *ctx, ValueRef result, String *name)
{
Value res = Value::fromBoolean(ctx->deleteProperty(name));
if (result)
*result = res;
}
-void __qmljs_add_helper(ExecutionContext *ctx, Value *result, const Value &left, const Value &right)
+void __qmljs_add_helper(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
{
- Value pleft = __qmljs_to_primitive(left, PREFERREDTYPE_HINT);
- Value pright = __qmljs_to_primitive(right, PREFERREDTYPE_HINT);
- if (pleft.isString() || pright.isString()) {
- if (!pleft.isString())
+ ValueScope scope(ctx);
+
+ ScopedValue pleft(scope, __qmljs_to_primitive(left, PREFERREDTYPE_HINT));
+ ScopedValue pright(scope, __qmljs_to_primitive(right, PREFERREDTYPE_HINT));
+ if (pleft->isString() || pright->isString()) {
+ if (!pleft->isString())
pleft = __qmljs_to_string(pleft, ctx);
- if (!pright.isString())
+ if (!pright->isString())
pright = __qmljs_to_string(pright, ctx);
- String *string = __qmljs_string_concat(ctx, pleft.stringValue(), pright.stringValue());
+ String *string = __qmljs_string_concat(ctx, pleft->stringValue(), pright->stringValue());
*result = Value::fromString(string);
return;
}
@@ -175,212 +178,223 @@ void __qmljs_add_helper(ExecutionContext *ctx, Value *result, const Value &left,
*result = Value::fromDouble(x + y);
}
-void __qmljs_instanceof(ExecutionContext *ctx, Value *result, const Value &left, const Value &right)
+void __qmljs_instanceof(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
{
- Object *o = right.asObject();
+ Object *o = right->asObject();
if (!o)
ctx->throwTypeError();
- bool r = o->hasInstance(left);
+ bool r = o->hasInstance(*left);
*result = Value::fromBoolean(r);
}
-void __qmljs_in(ExecutionContext *ctx, Value *result, const Value &left, const Value &right)
+void __qmljs_in(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
{
- if (!right.isObject())
+ if (!right->isObject())
ctx->throwTypeError();
- String *s = left.toString(ctx);
- bool r = right.objectValue()->__hasProperty__(s);
+ String *s = left->toString(ctx);
+ bool r = right->objectValue()->__hasProperty__(s);
*result = Value::fromBoolean(r);
}
-void __qmljs_inplace_bit_and_name(ExecutionContext *ctx, String *name, const Value &value)
+static void inplaceBitOp(ExecutionContext *ctx, String *name, const ValueRef value, BinOp op)
+{
+ ValueScope scope(ctx);
+ ScopedValue lhs(scope, ctx->getProperty(name));
+ ScopedValue result(scope);
+ op(result, lhs, value);
+ ctx->setProperty(name, result);
+}
+
+
+void __qmljs_inplace_bit_and_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_bit_and);
+ inplaceBitOp(ctx, name, value, __qmljs_bit_and);
}
-void __qmljs_inplace_bit_or_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_bit_or_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_bit_or);
+ inplaceBitOp(ctx, name, value, __qmljs_bit_or);
}
-void __qmljs_inplace_bit_xor_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_bit_xor_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_bit_xor);
+ inplaceBitOp(ctx, name, value, __qmljs_bit_xor);
}
-void __qmljs_inplace_add_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_add_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- Value lhs = ctx->getProperty(name);
- Value result;
- __qmljs_add(ctx, &result, lhs, value);
+ ValueScope scope(ctx);
+ ScopedValue lhs(scope, ctx->getProperty(name));
+ ScopedValue result(scope);
+ __qmljs_add(ctx, result, lhs, value);
ctx->setProperty(name, result);
}
-void __qmljs_inplace_sub_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_sub_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_sub);
+ inplaceBitOp(ctx, name, value, __qmljs_sub);
}
-void __qmljs_inplace_mul_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_mul_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_mul);
+ inplaceBitOp(ctx, name, value, __qmljs_mul);
}
-void __qmljs_inplace_div_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_div_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_div);
+ inplaceBitOp(ctx, name, value, __qmljs_div);
}
-void __qmljs_inplace_mod_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_mod_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_mod);
+ inplaceBitOp(ctx, name, value, __qmljs_mod);
}
-void __qmljs_inplace_shl_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_shl_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_shl);
+ inplaceBitOp(ctx, name, value, __qmljs_shl);
}
-void __qmljs_inplace_shr_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_shr_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_shr);
+ inplaceBitOp(ctx, name, value, __qmljs_shr);
}
-void __qmljs_inplace_ushr_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_ushr_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_ushr);
+ inplaceBitOp(ctx, name, value, __qmljs_ushr);
}
-void __qmljs_inplace_bit_and_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_bit_and_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_bit_and, index, rhs);
}
-void __qmljs_inplace_bit_or_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_bit_or_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_bit_or, index, rhs);
}
-void __qmljs_inplace_bit_xor_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_bit_xor_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_bit_xor, index, rhs);
}
-void __qmljs_inplace_add_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_add_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_add, index, rhs);
}
-void __qmljs_inplace_sub_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_sub_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_sub, index, rhs);
}
-void __qmljs_inplace_mul_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_mul_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_mul, index, rhs);
}
-void __qmljs_inplace_div_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_div_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_div, index, rhs);
}
-void __qmljs_inplace_mod_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_mod_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_mod, index, rhs);
}
-void __qmljs_inplace_shl_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_shl_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_shl, index, rhs);
}
-void __qmljs_inplace_shr_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_shr_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_shr, index, rhs);
}
-void __qmljs_inplace_ushr_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_ushr_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_ushr, index, rhs);
}
-void __qmljs_inplace_bit_and_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_bit_and_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_bit_and, name, rhs);
}
-void __qmljs_inplace_bit_or_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_bit_or_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_bit_or, name, rhs);
}
-void __qmljs_inplace_bit_xor_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_bit_xor_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_bit_xor, name, rhs);
}
-void __qmljs_inplace_add_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_add_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_add, name, rhs);
}
-void __qmljs_inplace_sub_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_sub_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_sub, name, rhs);
}
-void __qmljs_inplace_mul_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_mul_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_mul, name, rhs);
}
-void __qmljs_inplace_div_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_div_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_div, name, rhs);
}
-void __qmljs_inplace_mod_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_mod_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_mod, name, rhs);
}
-void __qmljs_inplace_shl_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_shl_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_shl, name, rhs);
}
-void __qmljs_inplace_shr_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_shr_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_shr, name, rhs);
}
-void __qmljs_inplace_ushr_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_ushr_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_ushr, name, rhs);
}
@@ -446,18 +460,18 @@ Value __qmljs_object_default_value(Object *object, int typeHint)
Value conv = object->get(meth1);
if (FunctionObject *o = conv.asFunctionObject()) {
- CALLDATA(0);
- d.thisObject = Value::fromObject(object);
- Value r = o->call(d);
+ ScopedCallData callData(engine, 0);
+ callData->thisObject = Value::fromObject(object);
+ Value r = o->call(callData);
if (r.isPrimitive())
return r;
}
conv = object->get(meth2);
if (FunctionObject *o = conv.asFunctionObject()) {
- CALLDATA(0);
- d.thisObject = Value::fromObject(object);
- Value r = o->call(d);
+ ScopedCallData callData(engine, 0);
+ callData->thisObject = Value::fromObject(object);
+ Value r = o->call(callData);
if (r.isPrimitive())
return r;
}
@@ -466,74 +480,74 @@ Value __qmljs_object_default_value(Object *object, int typeHint)
return Value::undefinedValue();
}
-Bool __qmljs_to_boolean(const Value &value)
+Bool __qmljs_to_boolean(const ValueRef value)
{
- return value.toBoolean();
+ return value->toBoolean();
}
-Object *__qmljs_convert_to_object(ExecutionContext *ctx, const Value &value)
+Object *__qmljs_convert_to_object(ExecutionContext *ctx, const ValueRef value)
{
- assert(!value.isObject());
- switch (value.type()) {
+ assert(!value->isObject());
+ switch (value->type()) {
case Value::Undefined_Type:
case Value::Null_Type:
ctx->throwTypeError();
case Value::Boolean_Type:
- return ctx->engine->newBooleanObject(value);
+ return ctx->engine->newBooleanObject(*value);
case Value::String_Type:
- return ctx->engine->newStringObject(value);
+ return ctx->engine->newStringObject(*value);
break;
case Value::Object_Type:
Q_UNREACHABLE();
case Value::Integer_Type:
default: // double
- return ctx->engine->newNumberObject(value);
+ return ctx->engine->newNumberObject(*value);
}
}
-String *__qmljs_convert_to_string(ExecutionContext *ctx, const Value &value)
+String *__qmljs_convert_to_string(ExecutionContext *ctx, const ValueRef value)
{
- switch (value.type()) {
+ switch (value->type()) {
case Value::Undefined_Type:
return ctx->engine->id_undefined;
case Value::Null_Type:
return ctx->engine->id_null;
case Value::Boolean_Type:
- if (value.booleanValue())
+ if (value->booleanValue())
return ctx->engine->id_true;
else
return ctx->engine->id_false;
case Value::String_Type:
- return value.stringValue();
+ return value->stringValue();
case Value::Object_Type: {
Value prim = __qmljs_to_primitive(value, STRING_HINT);
if (prim.isPrimitive())
- return __qmljs_convert_to_string(ctx, prim);
+ return __qmljs_convert_to_string(ctx, ValueRef(&prim));
else
ctx->throwTypeError();
}
case Value::Integer_Type:
- return __qmljs_string_from_number(ctx, value.int_32).stringValue();
+ return __qmljs_string_from_number(ctx, value->int_32).stringValue();
default: // double
- return __qmljs_string_from_number(ctx, value.doubleValue()).stringValue();
+ return __qmljs_string_from_number(ctx, value->doubleValue()).stringValue();
} // switch
}
-void __qmljs_set_property(ExecutionContext *ctx, const Value &object, String *name, const Value &value)
+void __qmljs_set_property(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value)
{
- Object *o = object.toObject(ctx);
- o->put(name, value);
+ Object *o = object->toObject(ctx);
+ o->put(name, *value);
}
-void __qmljs_get_element(ExecutionContext *ctx, Value *result, const Value &object, const Value &index)
+void __qmljs_get_element(ExecutionContext *ctx, ValueRef result, const ValueRef object, const ValueRef index)
{
- uint idx = index.asArrayIndex();
+ uint idx = index->asArrayIndex();
- Object *o = object.asObject();
+ Object *o = object->asObject();
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (String *str = object->asString()) {
if (idx >= (uint)str->toQString().length()) {
if (result)
*result = Value::undefinedValue();
@@ -546,8 +560,8 @@ void __qmljs_get_element(ExecutionContext *ctx, Value *result, const Value &obje
}
}
- if (object.isNull() || object.isUndefined()) {
- QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index.toQString()).arg(object.toQString());
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQString()).arg(object->toQString());
ctx->throwTypeError(message);
}
@@ -570,17 +584,17 @@ void __qmljs_get_element(ExecutionContext *ctx, Value *result, const Value &obje
return;
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
Value res = o->get(name);
if (result)
*result = res;
}
-void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value &index, const Value &value)
+void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value)
{
- Object *o = object.toObject(ctx);
+ Object *o = object->toObject(ctx);
- uint idx = index.asArrayIndex();
+ uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
uint pidx = o->propertyIndexFromArrayIndex(idx);
if (pidx < UINT_MAX) {
@@ -592,7 +606,7 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value
Property *p = o->arrayData + pidx;
if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
- p->value = value;
+ p->value = *value;
return;
}
@@ -604,55 +618,55 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value
return;
}
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(o);
- setter->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = Value::fromObject(o);
+ callData->args[0] = *value;
+ setter->call(callData);
return;
}
}
- o->putIndexed(idx, value);
+ o->putIndexed(idx, *value);
return;
}
- String *name = index.toString(ctx);
- o->put(name, value);
+ String *name = index->toString(ctx);
+ o->put(name, *value);
}
-void __qmljs_foreach_iterator_object(ExecutionContext *ctx, Value *result, const Value &in)
+void __qmljs_foreach_iterator_object(ExecutionContext *ctx, ValueRef result, const ValueRef in)
{
Object *o = 0;
- if (!in.isNull() && !in.isUndefined())
- o = in.toObject(ctx);
+ if (!in->isNullOrUndefined())
+ o = in->toObject(ctx);
Object *it = ctx->engine->newForEachIteratorObject(ctx, o);
*result = Value::fromObject(it);
}
-void __qmljs_foreach_next_property_name(Value *result, const Value &foreach_iterator)
+void __qmljs_foreach_next_property_name(ValueRef result, const ValueRef foreach_iterator)
{
- assert(foreach_iterator.isObject());
+ assert(foreach_iterator->isObject());
- ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator.objectValue());
+ ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator->objectValue());
assert(it->as<ForEachIteratorObject>());
*result = it->nextPropertyName();
}
-void __qmljs_set_activation_property(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_set_activation_property(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->setProperty(name, value);
+ ctx->setProperty(name, *value);
}
-void __qmljs_get_property(ExecutionContext *ctx, Value *result, const Value &object, String *name)
+void __qmljs_get_property(ExecutionContext *ctx, ValueRef result, const ValueRef object, String *name)
{
Value res;
- Managed *m = object.asManaged();
+ Managed *m = object->asManaged();
if (m) {
res = m->get(name);
} else {
- if (object.isNull() || object.isUndefined()) {
- QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object.toQString());
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQString());
ctx->throwTypeError(message);
}
@@ -663,62 +677,64 @@ void __qmljs_get_property(ExecutionContext *ctx, Value *result, const Value &obj
*result = res;
}
-void __qmljs_get_activation_property(ExecutionContext *ctx, Value *result, String *name)
+void __qmljs_get_activation_property(ExecutionContext *ctx, ValueRef result, String *name)
{
*result = ctx->getProperty(name);
}
-uint __qmljs_equal_helper(const Value &x, const Value &y)
+uint __qmljs_equal_helper(const ValueRef x, const ValueRef y)
{
- Q_ASSERT(x.type() != y.type());
+ Q_ASSERT(x->type() != y->type());
- if (x.isNumber() && y.isNumber())
- return x.asDouble() == y.asDouble();
- if (x.isNull() && y.isUndefined()) {
+ if (x->isNumber() && y->isNumber())
+ return x->asDouble() == y->asDouble();
+ if (x->isNull() && y->isUndefined()) {
return true;
- } else if (x.isUndefined() && y.isNull()) {
+ } else if (x->isUndefined() && y->isNull()) {
return true;
- } else if (x.isNumber() && y.isString()) {
+ } else if (x->isNumber() && y->isString()) {
double dy = __qmljs_to_number(y);
- return x.asDouble() == dy;
- } else if (x.isString() && y.isNumber()) {
+ return x->asDouble() == dy;
+ } else if (x->isString() && y->isNumber()) {
double dx = __qmljs_to_number(x);
- return dx == y.asDouble();
- } else if (x.isBoolean()) {
- Value nx = Value::fromDouble((double) x.booleanValue());
- return __qmljs_cmp_eq(nx, y);
- } else if (y.isBoolean()) {
- Value ny = Value::fromDouble((double) y.booleanValue());
- return __qmljs_cmp_eq(x, ny);
- } else if ((x.isNumber() || x.isString()) && y.isObject()) {
+ return dx == y->asDouble();
+ } else if (x->isBoolean()) {
+ Value nx = Value::fromDouble((double) x->booleanValue());
+ return __qmljs_cmp_eq(ValueRef(&nx), y);
+ } else if (y->isBoolean()) {
+ Value ny = Value::fromDouble((double) y->booleanValue());
+ return __qmljs_cmp_eq(x, ValueRef(&ny));
+ } else if ((x->isNumber() || x->isString()) && y->isObject()) {
Value py = __qmljs_to_primitive(y, PREFERREDTYPE_HINT);
- return __qmljs_cmp_eq(x, py);
- } else if (x.isObject() && (y.isNumber() || y.isString())) {
+ return __qmljs_cmp_eq(x, ValueRef(&py));
+ } else if (x->isObject() && (y->isNumber() || y->isString())) {
Value px = __qmljs_to_primitive(x, PREFERREDTYPE_HINT);
- return __qmljs_cmp_eq(px, y);
+ return __qmljs_cmp_eq(ValueRef(&px), y);
}
return false;
}
-Bool __qmljs_strict_equal(const Value &x, const Value &y)
+Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y)
{
TRACE2(x, y);
- if (x.rawValue() == y.rawValue())
+ if (x->rawValue() == y->rawValue())
// NaN != NaN
- return (x.tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
+ return (x->tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
- if (x.isNumber())
- return y.isNumber() && x.asDouble() == y.asDouble();
- if (x.isString())
- return y.isString() && x.stringValue()->isEqualTo(y.stringValue());
+ if (x->isNumber())
+ return y->isNumber() && x->asDouble() == y->asDouble();
+ if (x->isString())
+ return y->isString() && x->stringValue()->isEqualTo(y->stringValue());
return false;
}
-void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+void __qmljs_call_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Lookup *l = context->lookups + index;
Value v;
l->globalGetter(l, context, &v);
@@ -726,29 +742,28 @@ void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint i
if (!o)
context->throwTypeError();
- Value thisObject = Value::undefinedValue();
-
if (o == context->engine->evalFunction && l->name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(thisObject, args, argc, true);
+ Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
if (result)
*result = res;
return;
}
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
+void __qmljs_call_activation_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Object *base;
Value func = context->getPropertyAndBase(name, &base);
+ if (base)
+ callData->thisObject = Value::fromObject(base);
+
FunctionObject *o = func.asFunctionObject();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
@@ -758,110 +773,88 @@ void __qmljs_call_activation_property(ExecutionContext *context, Value *result,
context->throwTypeError(msg);
}
- Value thisObject = base ? Value::fromObject(base) : Value::undefinedValue();
-
if (o == context->engine->evalFunction && name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(thisObject, args, argc, true);
+ Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
if (result)
*result = res;
return;
}
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_property(ExecutionContext *context, Value *result, const Value &thatObject, String *name, Value *args, int argc)
+void __qmljs_call_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
{
- Value thisObject = thatObject;
- Managed *baseObject = thisObject.asManaged();
+ Managed *baseObject = callData->thisObject.asManaged();
if (!baseObject) {
- if (thisObject.isNull() || thisObject.isUndefined()) {
- QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(thisObject.toQString());
+ if (callData->thisObject.isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQString());
context->throwTypeError(message);
}
- baseObject = __qmljs_convert_to_object(context, thisObject);
- thisObject = Value::fromObject(static_cast<Object *>(baseObject));
+ baseObject = __qmljs_convert_to_object(context, ValueRef(&callData->thisObject));
+ callData->thisObject = Value::fromObject(static_cast<Object *>(baseObject));
}
- Value func = baseObject->get(name);
- FunctionObject *o = func.asFunctionObject();
+ FunctionObject *o = baseObject->get(name).asFunctionObject();
if (!o) {
- QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), thisObject.toQString());
+ QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQString());
context->throwTypeError(error);
}
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, const Value &thisObject, uint index, Value *args, int argc)
+void __qmljs_call_property_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
{
Value func;
Lookup *l = context->lookups + index;
- l->getter(l, &func, thisObject);
+ l->getter(l, &func, callData->thisObject);
Object *o = func.asObject();
if (!o)
context->throwTypeError();
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_element(ExecutionContext *context, Value *result, const Value &that, const Value &index, Value *args, int argc)
+void __qmljs_call_element(ExecutionContext *context, ValueRef result, const ValueRef index, CallDataRef callData)
{
- Object *baseObject = that.toObject(context);
- Value thisObject = Value::fromObject(baseObject);
+ Object *baseObject = callData->thisObject.toObject(context);
+ callData->thisObject = Value::fromObject(baseObject);
- Value func = baseObject->get(index.toString(context));
- Object *o = func.asObject();
+ Object *o = baseObject->get(index->toString(context)).asObject();
if (!o)
context->throwTypeError();
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_value(ExecutionContext *context, Value *result, const Value *thisObject, const Value &func, Value *args, int argc)
+void __qmljs_call_value(ExecutionContext *context, ValueRef result, const ValueRef func, CallDataRef callData)
{
- Object *o = func.asObject();
+ Object *o = func->asObject();
if (!o)
context->throwTypeError();
- CallData d;
- d.thisObject = thisObject ? *thisObject : Value::undefinedValue();
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+void __qmljs_construct_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Value func;
Lookup *l = context->lookups + index;
@@ -871,65 +864,60 @@ void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, u
if (!f)
context->throwTypeError();
- CallData d;
- d.args = args;
- d.argc = argc;
- Value res = f->construct(d);
+ Value res = f->construct(callData);
if (result)
*result = res;
}
-void __qmljs_construct_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
+void __qmljs_construct_activation_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
{
Value func = context->getProperty(name);
- __qmljs_construct_value(context, result, func, args, argc);
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
+
+ Value res = f->construct(callData);
+ if (result)
+ *result = res;
}
-void __qmljs_construct_value(ExecutionContext *context, Value *result, const Value &func, Value *args, int argc)
+void __qmljs_construct_value(ExecutionContext *context, ValueRef result, const ValueRef func, CallDataRef callData)
{
- if (Object *f = func.asObject()) {
- CallData d;
- d.args = args;
- d.argc = argc;
- Value res = f->construct(d);
- if (result)
- *result = res;
- return;
- }
+ Object *f = func->asObject();
+ if (!f)
+ context->throwTypeError();
- context->throwTypeError();
+ Value res = f->construct(callData);
+ if (result)
+ *result = res;
}
-void __qmljs_construct_property(ExecutionContext *context, Value *result, const Value &base, String *name, Value *args, int argc)
+void __qmljs_construct_property(ExecutionContext *context, ValueRef result, const ValueRef base, String *name, CallDataRef callData)
{
- Object *thisObject = base.toObject(context);
+ Object *thisObject = base->toObject(context);
Value func = thisObject->get(name);
- if (Object *f = func.asObject()) {
- CallData d;
- d.args = args;
- d.argc = argc;
- Value res = f->construct(d);
- if (result)
- *result = res;
- return;
- }
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
- context->throwTypeError();
+ Value res = f->construct(callData);
+ if (result)
+ *result = res;
}
-void __qmljs_throw(ExecutionContext *context, const Value &value)
+void __qmljs_throw(ExecutionContext *context, const ValueRef value)
{
- Exception::throwException(context, value);
+ Exception::throwException(context, *value);
}
-void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &value)
+void __qmljs_builtin_typeof(ExecutionContext *ctx, ValueRef result, const ValueRef value)
{
if (!result)
return;
String *res = 0;
- switch (value.type()) {
+ switch (value->type()) {
case Value::Undefined_Type:
res = ctx->engine->id_undefined;
break;
@@ -943,7 +931,7 @@ void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &v
res = ctx->engine->id_string;
break;
case Value::Object_Type:
- if (value.objectValue()->asFunctionObject())
+ if (value->objectValue()->asFunctionObject())
res = ctx->engine->id_function;
else
res = ctx->engine->id_object; // ### implementation-defined
@@ -955,36 +943,41 @@ void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &v
*result = Value::fromString(res);
}
-void __qmljs_builtin_typeof_name(ExecutionContext *context, Value *result, String *name)
+void __qmljs_builtin_typeof_name(ExecutionContext *context, ValueRef result, String *name)
{
- Value res;
- __qmljs_builtin_typeof(context, &res, context->getPropertyNoThrow(name));
+ ValueScope scope(context);
+ ScopedValue res(scope);
+ ScopedValue prop(scope, context->getPropertyNoThrow(name));
+ __qmljs_builtin_typeof(context, res, prop);
if (result)
*result = res;
}
-void __qmljs_builtin_typeof_member(ExecutionContext *context, Value *result, const Value &base,
+void __qmljs_builtin_typeof_member(ExecutionContext *context, ValueRef result, const ValueRef base,
String *name)
{
- Object *obj = base.toObject(context);
- Value res;
- __qmljs_builtin_typeof(context, &res, obj->get(name));
+ ValueScope scope(context);
+ Object *obj = base->toObject(context);
+ ScopedValue res(scope);
+ ScopedValue prop(scope, obj->get(name));
+ __qmljs_builtin_typeof(context, res, prop);
if (result)
*result = res;
}
-void __qmljs_builtin_typeof_element(ExecutionContext *context, Value *result, const Value &base,
- const Value &index)
+void __qmljs_builtin_typeof_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
{
- String *name = index.toString(context);
- Object *obj = base.toObject(context);
- Value res;
- __qmljs_builtin_typeof(context, &res, obj->get(name));
+ ValueScope scope(context);
+ String *name = index->toString(context);
+ Object *obj = base->toObject(context);
+ ScopedValue res(scope);
+ ScopedValue prop(scope, obj->get(name));
+ __qmljs_builtin_typeof(context, res, prop);
if (result)
*result = res;
}
-void __qmljs_builtin_post_increment(Value *result, Value *val)
+void __qmljs_builtin_post_increment(ValueRef result, ValueRef val)
{
if (val->isInteger() && val->integerValue() < INT_MAX) {
if (result)
@@ -993,13 +986,13 @@ void __qmljs_builtin_post_increment(Value *result, Value *val)
return;
}
- double d = __qmljs_to_number(*val);
+ double d = val->toNumber();
*val = Value::fromDouble(d + 1);
if (result)
*result = Value::fromDouble(d);
}
-void __qmljs_builtin_post_increment_name(ExecutionContext *context, Value *result, String *name)
+void __qmljs_builtin_post_increment_name(ExecutionContext *context, ValueRef result, String *name)
{
Value v = context->getProperty(name);
@@ -1008,7 +1001,7 @@ void __qmljs_builtin_post_increment_name(ExecutionContext *context, Value *resul
*result = v;
v.int_32 += 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d + 1);
@@ -1017,9 +1010,9 @@ void __qmljs_builtin_post_increment_name(ExecutionContext *context, Value *resul
context->setProperty(name, v);
}
-void __qmljs_builtin_post_increment_member(ExecutionContext *context, Value *result, const Value &base, String *name)
+void __qmljs_builtin_post_increment_member(ExecutionContext *context, ValueRef result, const ValueRef base, String *name)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
Value v = o->get(name);
@@ -1028,7 +1021,7 @@ void __qmljs_builtin_post_increment_member(ExecutionContext *context, Value *res
*result = v;
v.int_32 += 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d + 1);
@@ -1037,9 +1030,9 @@ void __qmljs_builtin_post_increment_member(ExecutionContext *context, Value *res
o->put(name, v);
}
-void __qmljs_builtin_post_increment_element(ExecutionContext *context, Value *result, const Value &base, const Value *index)
+void __qmljs_builtin_post_increment_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
uint idx = index->asArrayIndex();
@@ -1055,7 +1048,7 @@ void __qmljs_builtin_post_increment_element(ExecutionContext *context, Value *re
*result = v;
v.int_32 += 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d + 1);
@@ -1064,7 +1057,7 @@ void __qmljs_builtin_post_increment_element(ExecutionContext *context, Value *re
o->putIndexed(idx, v);
}
-void __qmljs_builtin_post_decrement(Value *result, Value *val)
+void __qmljs_builtin_post_decrement(ValueRef result, ValueRef val)
{
if (val->isInteger() && val->integerValue() > INT_MIN) {
if (result)
@@ -1073,13 +1066,13 @@ void __qmljs_builtin_post_decrement(Value *result, Value *val)
return;
}
- double d = __qmljs_to_number(*val);
+ double d = val->toNumber();
*val = Value::fromDouble(d - 1);
if (result)
*result = Value::fromDouble(d);
}
-void __qmljs_builtin_post_decrement_name(ExecutionContext *context, Value *result, String *name)
+void __qmljs_builtin_post_decrement_name(ExecutionContext *context, ValueRef result, String *name)
{
Value v = context->getProperty(name);
@@ -1088,7 +1081,7 @@ void __qmljs_builtin_post_decrement_name(ExecutionContext *context, Value *resul
*result = v;
v.int_32 -= 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d - 1);
@@ -1097,9 +1090,9 @@ void __qmljs_builtin_post_decrement_name(ExecutionContext *context, Value *resul
context->setProperty(name, v);
}
-void __qmljs_builtin_post_decrement_member(ExecutionContext *context, Value *result, const Value &base, String *name)
+void __qmljs_builtin_post_decrement_member(ExecutionContext *context, ValueRef result, const ValueRef base, String *name)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
Value v = o->get(name);
@@ -1108,7 +1101,7 @@ void __qmljs_builtin_post_decrement_member(ExecutionContext *context, Value *res
*result = v;
v.int_32 -= 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d - 1);
@@ -1117,14 +1110,14 @@ void __qmljs_builtin_post_decrement_member(ExecutionContext *context, Value *res
o->put(name, v);
}
-void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *result, const Value &base, const Value &index)
+void __qmljs_builtin_post_decrement_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
- uint idx = index.asArrayIndex();
+ uint idx = index->asArrayIndex();
if (idx == UINT_MAX) {
- String *s = index.toString(context);
+ String *s = index->toString(context);
return __qmljs_builtin_post_decrement_member(context, result, base, s);
}
@@ -1135,7 +1128,7 @@ void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *re
*result = v;
v.int_32 -= 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d - 1);
@@ -1144,15 +1137,15 @@ void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *re
o->putIndexed(idx, v);
}
-ExecutionContext *__qmljs_builtin_push_with_scope(const Value &o, ExecutionContext *ctx)
+ExecutionContext *__qmljs_builtin_push_with_scope(const ValueRef o, ExecutionContext *ctx)
{
- Object *obj = o.toObject(ctx);
+ Object *obj = o->toObject(ctx);
return ctx->newWithContext(obj);
}
-ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, const Value &exceptionValue, ExecutionContext *ctx)
+ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, const ValueRef exceptionValue, ExecutionContext *ctx)
{
- return ctx->newCatchContext(exceptionVarName, exceptionValue);
+ return ctx->newCatchContext(exceptionVarName, *exceptionValue);
}
ExecutionContext *__qmljs_builtin_pop_scope(ExecutionContext *ctx)
@@ -1165,9 +1158,9 @@ void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String *
ctx->createMutableBinding(name, deletable);
}
-void __qmljs_builtin_define_property(ExecutionContext *ctx, const Value &object, String *name, Value *val)
+void __qmljs_builtin_define_property(ExecutionContext *ctx, const ValueRef object, String *name, ValueRef val)
{
- Object *o = object.asObject();
+ Object *o = object->asObject();
assert(o);
uint idx = name->asArrayIndex();
@@ -1175,7 +1168,7 @@ void __qmljs_builtin_define_property(ExecutionContext *ctx, const Value &object,
pd->value = val ? *val : Value::undefinedValue();
}
-void __qmljs_builtin_define_array(ExecutionContext *ctx, Value *array, Value *values, uint length)
+void __qmljs_builtin_define_array(ExecutionContext *ctx, ValueRef array, Value *values, uint length)
{
ArrayObject *a = ctx->engine->newArrayObject();
@@ -1200,9 +1193,9 @@ void __qmljs_builtin_define_array(ExecutionContext *ctx, Value *array, Value *va
*array = Value::fromObject(a);
}
-void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const Value &object, String *name, const Value *getter, const Value *setter)
+void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef getter, const ValueRef setter)
{
- Object *o = object.asObject();
+ Object *o = object->asObject();
assert(o);
uint idx = name->asArrayIndex();
@@ -1211,7 +1204,7 @@ void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const Value &ob
pd->setSetter(setter ? setter->asFunctionObject() : 0);
}
-void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, int classId)
+void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, ValueRef result, const QV4::Value *args, int classId)
{
QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId];
Object *o = ctx->engine->newObject(klass);
@@ -1230,7 +1223,7 @@ void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Valu
*result = Value::fromObject(o);
}
-void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, Value *result)
+void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, ValueRef result)
{
assert(ctx->type >= ExecutionContext::Type_CallContext);
CallContext *c = static_cast<CallContext *>(ctx);
@@ -1238,38 +1231,38 @@ void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, Value *result
*result = Value::fromObject(args);
}
-void __qmljs_increment(Value *result, const Value &value)
+void __qmljs_increment(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- if (value.isInteger())
- *result = Value::fromInt32(value.integerValue() + 1);
+ if (value->isInteger())
+ *result = Value::fromInt32(value->integerValue() + 1);
else {
- double d = __qmljs_to_number(value);
+ double d = value->toNumber();
*result = Value::fromDouble(d + 1);
}
}
-void __qmljs_decrement(Value *result, const Value &value)
+void __qmljs_decrement(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- if (value.isInteger())
- *result = Value::fromInt32(value.integerValue() - 1);
+ if (value->isInteger())
+ *result = Value::fromInt32(value->integerValue() - 1);
else {
- double d = __qmljs_to_number(value);
+ double d = value->toNumber();
*result = Value::fromDouble(d - 1);
}
}
-void __qmljs_value_to_double(double *result, const Value &value)
+void __qmljs_value_to_double(double *result, const ValueRef value)
{
- *result = __qmljs_to_number(value);
+ *result = value->toNumber();
}
-int __qmljs_value_to_int32(const Value &value)
+int __qmljs_value_to_int32(const ValueRef value)
{
- return value.toInt32();
+ return value->toInt32();
}
int __qmljs_double_to_int32(const double &d)
@@ -1277,9 +1270,9 @@ int __qmljs_double_to_int32(const double &d)
return Value::toInt32(d);
}
-unsigned __qmljs_value_to_uint32(const Value &value)
+unsigned __qmljs_value_to_uint32(const ValueRef value)
{
- return value.toUInt32();
+ return value->toUInt32();
}
unsigned __qmljs_double_to_uint32(const double &d)
@@ -1287,12 +1280,12 @@ unsigned __qmljs_double_to_uint32(const double &d)
return Value::toUInt32(d);
}
-void __qmljs_value_from_string(Value *result, String *string)
+void __qmljs_value_from_string(ValueRef result, String *string)
{
*result = Value::fromString(string);
}
-void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, Value *result, int id)
+void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, ValueRef result, int id)
{
*result = ctx->compilationUnit->runtimeRegularExpressions[id];
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index b38f833ad0..d1ca86fddd 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -44,7 +44,7 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
#include "qv4math_p.h"
-
+#include "qv4scopedvalue_p.h"
#include <QtCore/QString>
#include <QtCore/qnumeric.h>
@@ -91,47 +91,47 @@ struct ExecutionEngine;
struct InternalClass;
// context
-void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_call_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &that, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_call_property_lookup(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &thisObject, uint index, QV4::Value *args, int argc);
-void __qmljs_call_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &that, const QV4::Value &index, QV4::Value *args, int argc);
-void __qmljs_call_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value *thisObject, const QV4::Value &func, QV4::Value *args, int argc);
-
-void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &func, QV4::Value *args, int argc);
-
-void __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &val);
-void __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::Value* result, QV4::String *name);
-void __qmljs_builtin_typeof_member(QV4::ExecutionContext* context, QV4::Value* result, const QV4::Value &base, QV4::String *name);
-void __qmljs_builtin_typeof_element(QV4::ExecutionContext* context, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
-
-void __qmljs_builtin_post_increment(QV4::Value *result, QV4::Value *val);
-void __qmljs_builtin_post_increment_name(QV4::ExecutionContext *context, QV4::Value *result, QV4::String *name);
-void __qmljs_builtin_post_increment_member(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name);
-void __qmljs_builtin_post_increment_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, const QV4::Value *index);
-
-void __qmljs_builtin_post_decrement(QV4::Value *result, QV4::Value *val);
-void __qmljs_builtin_post_decrement_name(QV4::ExecutionContext *context, QV4::Value *result, QV4::String *name);
-void __qmljs_builtin_post_decrement_member(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name);
-void __qmljs_builtin_post_decrement_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
+void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
+void __qmljs_call_property(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
+void __qmljs_call_property_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData);
+void __qmljs_call_element(ExecutionContext *context, ValueRef result, const ValueRef index, CallDataRef callData);
+void __qmljs_call_value(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef func, CallDataRef callData);
+
+void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
+void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name, CallDataRef callData);
+void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef func, CallDataRef callData);
+
+void __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef val);
+void __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
+void __qmljs_builtin_typeof_member(QV4::ExecutionContext* context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_builtin_typeof_element(QV4::ExecutionContext* context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+
+void __qmljs_builtin_post_increment(QV4::ValueRef result, QV4::ValueRef val);
+void __qmljs_builtin_post_increment_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
+void __qmljs_builtin_post_increment_member(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_builtin_post_increment_element(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+
+void __qmljs_builtin_post_decrement(QV4::ValueRef result, QV4::ValueRef val);
+void __qmljs_builtin_post_decrement_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
+void __qmljs_builtin_post_decrement_member(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_builtin_post_decrement_element(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
void Q_NORETURN __qmljs_builtin_rethrow(QV4::ExecutionContext *context);
-QV4::ExecutionContext *__qmljs_builtin_push_with_scope(const QV4::Value &o, QV4::ExecutionContext *ctx);
-QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::String *exceptionVarName, const QV4::Value &exceptionValue, QV4::ExecutionContext *ctx);
+QV4::ExecutionContext *__qmljs_builtin_push_with_scope(const QV4::ValueRef o, QV4::ExecutionContext *ctx);
+QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::String *exceptionVarName, const QV4::ValueRef exceptionValue, QV4::ExecutionContext *ctx);
QV4::ExecutionContext *__qmljs_builtin_pop_scope(QV4::ExecutionContext *ctx);
void __qmljs_builtin_declare_var(QV4::ExecutionContext *ctx, bool deletable, QV4::String *name);
-void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, QV4::Value *val);
-void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::Value *array, QV4::Value *values, uint length);
-void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, const QV4::Value *getter, const QV4::Value *setter);
-void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, int classId);
-void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, QV4::Value *result);
+void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, QV4::ValueRef val);
+void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::ValueRef array, QV4::Value *values, uint length);
+void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef getter, const QV4::ValueRef setter);
+void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::Value *args, int classId);
+void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, QV4::ValueRef result);
-void __qmljs_value_from_string(QV4::Value *result, QV4::String *string);
-void __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, QV4::Value *result, int id);
+void __qmljs_value_from_string(QV4::ValueRef result, QV4::String *string);
+void __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, QV4::ValueRef result, int id);
// constructors
-void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::Value *result, int functionId);
+void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::ValueRef result, int functionId);
// strings
Q_QML_EXPORT double __qmljs_string_to_number(const QString &s);
@@ -140,192 +140,172 @@ QV4::String *__qmljs_string_concat(QV4::ExecutionContext *ctx, QV4::String *firs
// objects
Q_QML_EXPORT QV4::Value __qmljs_object_default_value(QV4::Object *object, int typeHint);
-void __qmljs_set_activation_property(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value& value);
-void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, const QV4::Value &value);
-void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &object, QV4::String *name);
-void __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::String *name);
+void __qmljs_set_activation_property(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef object, QV4::String *name);
+void __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, QV4::String *name);
-void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, QV4::Value *args, int argc);
-void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, QV4::Value *args, int argc);
+void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::ValueRef result, uint index, CallDataRef callData);
+void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::ValueRef result, uint index, CallDataRef callData);
-void __qmljs_get_element(QV4::ExecutionContext *ctx, QV4::Value *retval, const QV4::Value &object, const QV4::Value &index);
-void __qmljs_set_element(QV4::ExecutionContext *ctx, const QV4::Value &object, const QV4::Value &index, const QV4::Value &value);
+void __qmljs_get_element(QV4::ExecutionContext *ctx, QV4::ValueRef retval, const QV4::ValueRef object, const QV4::ValueRef index);
+void __qmljs_set_element(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::ValueRef index, const QV4::ValueRef value);
// For each
-void __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &in);
-void __qmljs_foreach_next_property_name(QV4::Value *result, const QV4::Value &foreach_iterator);
+void __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef in);
+void __qmljs_foreach_next_property_name(QV4::ValueRef result, const ValueRef foreach_iterator);
// type conversion and testing
-QV4::Value __qmljs_to_primitive(const QV4::Value &value, int typeHint);
-Q_QML_EXPORT QV4::Bool __qmljs_to_boolean(const QV4::Value &value);
-double __qmljs_to_number(const QV4::Value &value);
-QV4::Value __qmljs_to_string(const QV4::Value &value, QV4::ExecutionContext *ctx);
-Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const QV4::Value &value);
+QV4::Value __qmljs_to_primitive(const ValueRef value, int typeHint);
+Q_QML_EXPORT QV4::Bool __qmljs_to_boolean(const QV4::ValueRef value);
+double __qmljs_to_number(const QV4::ValueRef value);
+QV4::Value __qmljs_to_string(const ValueRef value, QV4::ExecutionContext *ctx);
+Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const ValueRef value);
void __qmljs_numberToString(QString *result, double num, int radix = 10);
-QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
-QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
+QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
+QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
-QV4::Bool __qmljs_equal_helper(const Value &x, const Value &y);
-Q_QML_EXPORT QV4::Bool __qmljs_strict_equal(const QV4::Value &x, const QV4::Value &y);
+QV4::Bool __qmljs_equal_helper(const ValueRef x, const ValueRef y);
+Q_QML_EXPORT QV4::Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y);
// unary operators
-typedef void (*UnaryOpName)(QV4::Value *, const QV4::Value &);
-void __qmljs_uplus(QV4::Value *result, const QV4::Value &value);
-void __qmljs_uminus(QV4::Value *result, const QV4::Value &value);
-void __qmljs_compl(QV4::Value *result, const QV4::Value &value);
-void __qmljs_not(QV4::Value *result, const QV4::Value &value);
-void __qmljs_increment(QV4::Value *result, const QV4::Value &value);
-void __qmljs_decrement(QV4::Value *result, const QV4::Value &value);
-
-Q_QML_EXPORT void __qmljs_value_to_double(double *result, const Value &value);
-Q_QML_EXPORT int __qmljs_value_to_int32(const Value &value);
+typedef void (*UnaryOpName)(QV4::ValueRef, const QV4::ValueRef);
+void __qmljs_uplus(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_uminus(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_compl(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_not(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_increment(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_decrement(QV4::ValueRef result, const QV4::ValueRef value);
+
+Q_QML_EXPORT void __qmljs_value_to_double(double *result, const ValueRef value);
+Q_QML_EXPORT int __qmljs_value_to_int32(const ValueRef value);
Q_QML_EXPORT int __qmljs_double_to_int32(const double &d);
-Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const Value &value);
+Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const ValueRef value);
Q_QML_EXPORT unsigned __qmljs_double_to_uint32(const double &d);
-void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
-void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, QV4::String *name);
-void __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::String *name);
+void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::ValueRef result, QV4::String *name);
-void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::Value &value);
+void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::ValueRef value);
// binary operators
-typedef void (*BinOp)(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-typedef void (*BinOpContext)(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-
-void __qmljs_instanceof(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_in(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_add(ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_bit_or(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_bit_xor(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_bit_and(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_sub(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_mul(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_div(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_mod(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_shl(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_shr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_ushr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_gt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_lt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_ge(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_le(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_eq(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_ne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_se(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_sne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-
-void __qmljs_add_helper(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-
-
-typedef void (*InplaceBinOpName)(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_bit_and_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_bit_or_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_bit_xor_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_add_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_sub_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_mul_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_div_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_mod_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_shl_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_shr_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_ushr_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-
-typedef void (*InplaceBinOpElement)(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_bit_and_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_bit_or_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_bit_xor_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_add_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_sub_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_mul_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_div_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_mod_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_shl_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_shr_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_ushr_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-
-typedef void (*InplaceBinOpMember)(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_bit_and_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_bit_or_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_bit_xor_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_add_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_sub_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_mul_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_div_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_mod_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_shl_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_shr_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_ushr_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-
-typedef QV4::Bool (*CmpOp)(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_gt(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_lt(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_ge(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_le(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_eq(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_ne(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_se(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_sne(const QV4::Value &left, const QV4::Value &right);
-
-typedef QV4::Bool (*CmpOpContext)(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right);
+typedef void (*BinOp)(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+typedef void (*BinOpContext)(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+
+void __qmljs_instanceof(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_in(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_add(ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_bit_or(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_bit_xor(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_bit_and(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_sub(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_mul(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_div(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_mod(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_shl(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_shr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_gt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_lt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_ge(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_le(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_eq(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_ne(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_se(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_sne(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+
+void __qmljs_add_helper(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+
+
+typedef void (*InplaceBinOpName)(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_bit_and_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_bit_or_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_bit_xor_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_add_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_sub_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_mul_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_div_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_mod_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_shl_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_shr_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_ushr_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+
+typedef void (*InplaceBinOpElement)(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_and_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_or_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_xor_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_add_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_sub_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_mul_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_div_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_mod_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_shl_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_shr_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_ushr_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+
+typedef void (*InplaceBinOpMember)(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_and_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_or_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_xor_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_add_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_sub_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_mul_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_div_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_mod_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_shl_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_shr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_ushr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+
+typedef QV4::Bool (*CmpOp)(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_ne(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_se(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_sne(const QV4::ValueRef left, const QV4::ValueRef right);
+
+typedef QV4::Bool (*CmpOpContext)(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
// type conversion and testing
-inline QV4::Value __qmljs_to_primitive(const QV4::Value &value, int typeHint)
+inline QV4::Value __qmljs_to_primitive(const QV4::ValueRef value, int typeHint)
{
- QV4::Object *o = value.asObject();
+ QV4::Object *o = value->asObject();
if (!o)
- return value;
+ return *value;
return __qmljs_object_default_value(o, typeHint);
}
-inline double __qmljs_to_number(const QV4::Value &value)
-{
- switch (value.type()) {
- case QV4::Value::Undefined_Type:
- return std::numeric_limits<double>::quiet_NaN();
- case QV4::Value::Null_Type:
- return 0;
- case QV4::Value::Boolean_Type:
- return (value.booleanValue() ? 1. : 0.);
- case QV4::Value::Integer_Type:
- return value.int_32;
- case QV4::Value::String_Type:
- return __qmljs_string_to_number(value.stringValue()->toQString());
- case QV4::Value::Object_Type: {
- QV4::Value prim = __qmljs_to_primitive(value, QV4::NUMBER_HINT);
- return __qmljs_to_number(prim);
- }
- default: // double
- return value.doubleValue();
- }
+inline double __qmljs_to_number(const ValueRef value)
+{
+ return value->toNumber();
}
-Q_QML_EXPORT int __qmljs_value_to_int32(const QV4::Value &value);
-Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const QV4::Value &value);
-
-inline QV4::Value __qmljs_to_string(const QV4::Value &value, QV4::ExecutionContext *ctx)
+inline QV4::Value __qmljs_to_string(const QV4::ValueRef value, QV4::ExecutionContext *ctx)
{
- if (value.isString())
- return value;
+ if (value->isString())
+ return *value;
return QV4::Value::fromString(__qmljs_convert_to_string(ctx, value));
}
-inline QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value)
+inline QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::ValueRef value)
{
- if (value.isObject())
- return value;
+ if (value->isObject())
+ return *value;
return QV4::Value::fromObject(__qmljs_convert_to_object(ctx, value));
}
-inline void __qmljs_uplus(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_uplus(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- *result = value;
+ result = value;
if (result->tryIntegerConversion())
return;
@@ -333,47 +313,47 @@ inline void __qmljs_uplus(QV4::Value *result, const QV4::Value &value)
*result = QV4::Value::fromDouble(n);
}
-inline void __qmljs_uminus(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_uminus(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
// +0 != -0, so we need to convert to double when negating 0
- if (value.isInteger() && value.integerValue())
- *result = QV4::Value::fromInt32(-value.integerValue());
+ if (value->isInteger() && value->integerValue())
+ *result = QV4::Value::fromInt32(-value->integerValue());
else {
double n = __qmljs_to_number(value);
*result = QV4::Value::fromDouble(-n);
}
}
-inline void __qmljs_compl(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_compl(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
int n;
- if (value.isConvertibleToInt())
- n = value.int_32;
+ if (value->isConvertibleToInt())
+ n = value->int_32;
else
n = QV4::Value::toInt32(__qmljs_to_number(value));
*result = QV4::Value::fromInt32(~n);
}
-inline void __qmljs_not(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_not(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- bool b = value.toBoolean();
+ bool b = value->toBoolean();
*result = QV4::Value::fromBoolean(!b);
}
// binary operators
-inline void __qmljs_bit_or(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_bit_or(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() | right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() | right->integerValue());
return;
}
@@ -382,12 +362,12 @@ inline void __qmljs_bit_or(QV4::Value *result, const QV4::Value &left, const QV4
*result = QV4::Value::fromInt32(lval | rval);
}
-inline void __qmljs_bit_xor(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_bit_xor(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() ^ right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() ^ right->integerValue());
return;
}
@@ -396,12 +376,12 @@ inline void __qmljs_bit_xor(QV4::Value *result, const QV4::Value &left, const QV
*result = QV4::Value::fromInt32(lval ^ rval);
}
-inline void __qmljs_bit_and(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_bit_and(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() & right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() & right->integerValue());
return;
}
@@ -410,29 +390,29 @@ inline void __qmljs_bit_and(QV4::Value *result, const QV4::Value &left, const QV
*result = QV4::Value::fromInt32(lval & rval);
}
-inline void __qmljs_add(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_add(QV4::ExecutionContext *ctx, ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = add_int32(left.integerValue(), right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = add_int32(left->integerValue(), right->integerValue());
return;
}
- if (QV4::Value::bothDouble(left, right)) {
- *result = QV4::Value::fromDouble(left.doubleValue() + right.doubleValue());
+ if (QV4::Value::bothDouble(*left, *right)) {
+ *result = QV4::Value::fromDouble(left->doubleValue() + right->doubleValue());
return;
}
__qmljs_add_helper(ctx, result, left, right);
}
-inline void __qmljs_sub(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_sub(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = sub_int32(left.integerValue(), right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = sub_int32(left->integerValue(), right->integerValue());
return;
}
@@ -441,12 +421,12 @@ inline void __qmljs_sub(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(lval - rval);
}
-inline void __qmljs_mul(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_mul(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = mul_int32(left.integerValue(), right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = mul_int32(left->integerValue(), right->integerValue());
return;
}
@@ -455,7 +435,7 @@ inline void __qmljs_mul(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(lval * rval);
}
-inline void __qmljs_div(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_div(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -464,13 +444,13 @@ inline void __qmljs_div(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(lval / rval);
}
-inline void __qmljs_mod(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_mod(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right) && right.integerValue() != 0) {
- int intRes = left.integerValue() % right.integerValue();
- if (intRes != 0 || left.integerValue() >= 0) {
+ if (QV4::Value::integerCompatible(*left, *right) && right->integerValue() != 0) {
+ int intRes = left->integerValue() % right->integerValue();
+ if (intRes != 0 || left->integerValue() >= 0) {
*result = QV4::Value::fromInt32(intRes);
return;
}
@@ -481,12 +461,12 @@ inline void __qmljs_mod(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(std::fmod(lval, rval));
}
-inline void __qmljs_shl(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_shl(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() << ((uint(right.integerValue()) & 0x1f)));
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() << ((uint(right->integerValue()) & 0x1f)));
return;
}
@@ -495,12 +475,12 @@ inline void __qmljs_shl(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromInt32(lval << rval);
}
-inline void __qmljs_shr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_shr(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() >> ((uint(right.integerValue()) & 0x1f)));
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() >> ((uint(right->integerValue()) & 0x1f)));
return;
}
@@ -509,13 +489,13 @@ inline void __qmljs_shr(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromInt32(lval >> rval);
}
-inline void __qmljs_ushr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
uint res;
- if (QV4::Value::integerCompatible(left, right)) {
- res = uint(left.integerValue()) >> (uint(right.integerValue()) & 0x1f);
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ res = uint(left->integerValue()) >> (uint(right->integerValue()) & 0x1f);
} else {
unsigned lval = QV4::Value::toUInt32(__qmljs_to_number(left));
unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
@@ -528,49 +508,49 @@ inline void __qmljs_ushr(QV4::Value *result, const QV4::Value &left, const QV4::
*result = QV4::Value::fromInt32(res);
}
-inline void __qmljs_gt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_gt(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_gt(left, right));
}
-inline void __qmljs_lt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_lt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_lt(left, right));
}
-inline void __qmljs_ge(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_ge(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_ge(left, right));
}
-inline void __qmljs_le(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_le(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_le(left, right));
}
-inline void __qmljs_eq(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_eq(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_eq(left, right));
}
-inline void __qmljs_ne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_ne(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(!__qmljs_cmp_eq(left, right));
}
-inline void __qmljs_se(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_se(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -578,7 +558,7 @@ inline void __qmljs_se(QV4::Value *result, const QV4::Value &left, const QV4::Va
*result = QV4::Value::fromBoolean(r);
}
-inline void __qmljs_sne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_sne(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -586,12 +566,13 @@ inline void __qmljs_sne(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromBoolean(r);
}
-inline QV4::Bool __qmljs_cmp_gt(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() > right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() > right->integerValue();
+ // Safe, as l & r are primitive values
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -600,17 +581,17 @@ inline QV4::Bool __qmljs_cmp_gt(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return r.stringValue()->compare(l.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl > dr;
}
}
-inline QV4::Bool __qmljs_cmp_lt(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() < right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() < right->integerValue();
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -620,17 +601,17 @@ inline QV4::Bool __qmljs_cmp_lt(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return l.stringValue()->compare(r.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl < dr;
}
}
-inline QV4::Bool __qmljs_cmp_ge(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() >= right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() >= right->integerValue();
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -640,17 +621,17 @@ inline QV4::Bool __qmljs_cmp_ge(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return !l.stringValue()->compare(r.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl >= dr;
}
}
-inline QV4::Bool __qmljs_cmp_le(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() <= right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() <= right->integerValue();
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -660,51 +641,51 @@ inline QV4::Bool __qmljs_cmp_le(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return !r.stringValue()->compare(l.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl <= dr;
}
}
-inline QV4::Bool __qmljs_cmp_eq(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (left.val == right.val)
+ if (left->val == right->val)
// NaN != NaN
- return (left.tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
+ return (left->tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
- if (left.type() == right.type()) {
- if (left.isManaged())
- return left.managed()->isEqualTo(right.managed());
+ if (left->type() == right->type()) {
+ if (left->isManaged())
+ return left->managed()->isEqualTo(right->managed());
return false;
}
return __qmljs_equal_helper(left, right);
}
-inline QV4::Bool __qmljs_cmp_ne(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_ne(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
return !__qmljs_cmp_eq(left, right);
}
-inline QV4::Bool __qmljs_cmp_se(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_se(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
return __qmljs_strict_equal(left, right);
}
-inline QV4::Bool __qmljs_cmp_sne(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_sne(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
return ! __qmljs_strict_equal(left, right);
}
-inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -713,7 +694,7 @@ inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::V
return v.booleanValue();
}
-inline uint __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right)
+inline uint __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
new file mode 100644
index 0000000000..a0e0d784a7
--- /dev/null
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4SCOPEDVALUE_P_H
+#define QV4SCOPEDVALUE_P_H
+
+#include "qv4engine_p.h"
+#include "qv4value_def_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define SAVE_JS_STACK(ctx) Value *__jsStack = ctx->engine->jsStackTop
+#define CHECK_JS_STACK(ctx) Q_ASSERT(__jsStack == ctx->engine->jsStackTop)
+
+namespace QV4 {
+
+struct ScopedValueArray {
+ ScopedValueArray(ExecutionEngine *e, int size)
+ : engine(e)
+#ifndef QT_NO_DEBUG
+ , size(size)
+#endif
+ {
+ ptr = e->stackPush(size);
+ }
+
+ ~ScopedValueArray() {
+#ifndef QT_NO_DEBUG
+ engine->stackPop(size);
+ Q_ASSERT(engine->jsStackTop == ptr);
+#else
+ engine->jsStackTop = ptr;
+#endif
+ }
+
+ ExecutionEngine *engine;
+#ifndef QT_NO_DEBUG
+ int size;
+#endif
+ Value *ptr;
+};
+
+struct ScopedValue;
+
+struct ValueScope {
+ ValueScope(ExecutionContext *ctx)
+ : engine(ctx->engine)
+ {
+ mark = ctx->engine->jsStackTop;
+ }
+
+ ValueScope(ExecutionEngine *e)
+ : engine(e)
+ {
+ mark = e->jsStackTop;
+ }
+
+ ~ValueScope() {
+ Q_ASSERT(engine->jsStackTop >= mark);
+ engine->jsStackTop = mark;
+ }
+
+ ExecutionEngine *engine;
+ Value *mark;
+};
+
+struct ScopedValue;
+struct ValueRef;
+
+struct ReturnedValue
+{
+ ReturnedValue(const Value &v)
+ : v(v) {}
+ // no destructor
+
+
+private:
+ friend struct ValueRef;
+ friend struct ScopedValue;
+ QV4::Value v;
+};
+
+struct ScopedValue
+{
+ ScopedValue(const ValueScope &scope)
+ {
+ ptr = scope.engine->jsStackTop++;
+ }
+
+ ScopedValue(const ValueScope &scope, const Value &v)
+ {
+ ptr = scope.engine->jsStackTop++;
+ *ptr = v;
+ }
+
+ ScopedValue(const ValueScope &scope, const ReturnedValue &v)
+ {
+ ptr = scope.engine->jsStackTop++;
+ *ptr = v.v;
+ }
+
+ ScopedValue &operator=(const Value &v) {
+ *ptr = v;
+ return *this;
+ }
+
+ ScopedValue &operator=(const ReturnedValue &v) {
+ *ptr = v.v;
+ return *this;
+ }
+
+ ScopedValue &operator=(const ScopedValue &other) {
+ *ptr = *other.ptr;
+ return *this;
+ }
+
+ Value *operator->() {
+ return ptr;
+ }
+
+ operator const Value &() const {
+ return *ptr;
+ }
+
+ Value *ptr;
+};
+
+struct ScopedCallData {
+ ScopedCallData(ExecutionEngine *e, int argc)
+ : engine(e)
+ // ### this check currently won't work because of exceptions
+#ifndef QT_NO_DEBUG
+ , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value))
+#endif
+ {
+ ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value)));
+ ptr->tag = 0;
+ ptr->argc = argc;
+ }
+
+ ~ScopedCallData() {
+#ifndef QT_NO_DEBUG
+ engine->stackPop(size);
+ Q_ASSERT((void *)engine->jsStackTop == (void *)ptr);
+#else
+ engine->jsStackTop = reinterpret_cast<Value *>(ptr);
+#endif
+ }
+
+ CallData *operator->() {
+ return ptr;
+ }
+
+ operator CallData *() const {
+ return ptr;
+ }
+
+
+ ExecutionEngine *engine;
+#ifndef QT_NO_DEBUG
+ int size;
+#endif
+ CallData *ptr;
+};
+
+struct ValueRef {
+ ValueRef(const ScopedValue &v)
+ : ptr(v.ptr) {}
+ ValueRef(const PersistentValue &v)
+ : ptr(&v.d->value) {}
+ ValueRef(PersistentValuePrivate *p)
+ : ptr(&p->value) {}
+ // Important: Do NOT add a copy constructor to this class
+ // adding a copy constructor actually changes the calling convention, ie.
+ // is not even binary compatible. Adding it would break assumptions made
+ // in the jit'ed code.
+ ValueRef &operator=(const ScopedValue &o)
+ { *ptr = *o.ptr; return *this; }
+ ValueRef &operator=(const ValueRef &o)
+ { *ptr = *o.ptr; return *this; }
+ ValueRef &operator=(const Value &v)
+ { *ptr = v; return *this; }
+ ValueRef &operator=(const ReturnedValue &v) {
+ *ptr = v.v;
+ return *this;
+ }
+
+ operator const Value *() const {
+ return ptr;
+ }
+ const Value *operator->() const {
+ return ptr;
+ }
+
+ operator Value *() {
+ return ptr;
+ }
+ Value *operator->() {
+ return ptr;
+ }
+
+ static ValueRef fromRawValue(Value *v) {
+ return ValueRef(v);
+ }
+ static const ValueRef fromRawValue(const Value *v) {
+ return ValueRef(const_cast<Value *>(v));
+ }
+ // ### get rid of this one!
+ ValueRef(Value *v) { ptr = v; }
+private:
+ Value *ptr;
+};
+
+
+struct CallDataRef {
+ CallDataRef(const ScopedCallData &c)
+ : ptr(c.ptr) {}
+ CallDataRef(CallData *v) { ptr = v; }
+ // Important: Do NOT add a copy constructor to this class
+ // adding a copy constructor actually changes the calling convention, ie.
+ // is not even binary compatible. Adding it would break assumptions made
+ // in the jit'ed code.
+ CallDataRef &operator=(const ScopedCallData &c)
+ { *ptr = *c.ptr; return *this; }
+ CallDataRef &operator=(const CallDataRef &o)
+ { *ptr = *o.ptr; return *this; }
+
+ operator const CallData *() const {
+ return ptr;
+ }
+ const CallData *operator->() const {
+ return ptr;
+ }
+
+ operator CallData *() {
+ return ptr;
+ }
+ CallData *operator->() {
+ return ptr;
+ }
+
+private:
+ CallData *ptr;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index aef8ac8838..16bab966e9 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -46,6 +46,7 @@
#include "qv4context_p.h"
#include "qv4debugging_p.h"
#include "qv4exception_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -74,7 +75,7 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec
scope->engine->popContext();
}
-Value QmlBindingWrapper::call(Managed *that, const CallData &)
+Value QmlBindingWrapper::call(Managed *that, CallData *)
{
ExecutionEngine *engine = that->engine();
QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
@@ -237,9 +238,9 @@ Value Script::run()
} else {
FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject());
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- return f->call(d);
+ ScopedCallData callData(scope->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ return f->call(callData);
}
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index b3bce6b427..b00e076a2b 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -56,7 +56,7 @@ struct QmlBindingWrapper : FunctionObject {
QmlBindingWrapper(ExecutionContext *scope, Function *f, Object *qml);
- static Value call(Managed *that, const CallData &);
+ static Value call(Managed *that, CallData *);
static void markObjects(Managed *m);
private:
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index b7f7317c76..29ca34910c 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -46,6 +46,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4arrayobject_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -351,11 +352,11 @@ public:
bool operator()(typename Container::value_type lhs, typename Container::value_type rhs)
{
QV4::Managed *fun = this->m_compareFn.asManaged();
- CALLDATA(2);
- d.args[0] = convertElementToValue(this->m_ctx->engine, lhs);
- d.args[1] = convertElementToValue(this->m_ctx->engine, rhs);
- d.thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject);
- QV4::Value result = fun->call(d);
+ ScopedCallData callData(fun->engine(), 2);
+ callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs);
+ callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs);
+ callData->thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject);
+ QV4::Value result = fun->call(callData);
return result.toNumber() < 0;
}
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 835a0d004f..f21855ebc9 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -43,6 +43,7 @@
#include "qv4runtime_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4scopedvalue_p.h"
#include <stdlib.h>
#ifdef QT_QMAP_DEBUG
@@ -54,20 +55,21 @@ using namespace QV4;
bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) const
{
- Value v1 = p1.value;
- Value v2 = p2.value;
- if (v1.isUndefined())
+ if (p1.value.isUndefined())
return false;
- if (v2.isUndefined())
+ if (p2.value.isUndefined())
return true;
- if (!m_comparefn.isUndefined()) {
- Value args[] = { v1, v2 };
+ if (Object *o = m_comparefn.asObject()) {
+ ScopedCallData callData(o->engine(), 2);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = p1.value;
+ callData->args[1] = p2.value;
Value result = Value::undefinedValue();
- __qmljs_call_value(m_context, &result, /*thisObject*/0, m_comparefn, args, 2);
+ __qmljs_call_value(m_context, &result, QV4::ValueRef::fromRawValue(&m_comparefn), callData);
return result.toNumber() <= 0;
}
- return v1.toString(m_context)->toQString() < v2.toString(m_context)->toQString();
+ return p1.value.toString(m_context)->toQString() < p2.value.toString(m_context)->toQString();
}
diff --git a/src/qml/jsruntime/qv4stacktrace.cpp b/src/qml/jsruntime/qv4stacktrace.cpp
index b0fabfd42e..2a27c57e46 100644
--- a/src/qml/jsruntime/qv4stacktrace.cpp
+++ b/src/qml/jsruntime/qv4stacktrace.cpp
@@ -137,7 +137,7 @@ NativeFrame NativeStackTrace::nextFrame() {
continue;
frame.function = f;
- frame.line = f->lineNumberForProgramCounter(pc - reinterpret_cast<quintptr>(f->code));
+ frame.line = f->lineNumberForProgramCounter(pc - reinterpret_cast<quintptr>(f->codePtr));
}
return frame;
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 52d98502a3..0a9cb32e6f 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -44,6 +44,7 @@
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -159,21 +160,21 @@ StringCtor::StringCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value StringCtor::construct(Managed *m, const CallData &d)
+Value StringCtor::construct(Managed *m, CallData *callData)
{
Value value;
- if (d.argc)
- value = Value::fromString(d.args[0].toString(m->engine()->current));
+ if (callData->argc)
+ value = Value::fromString(callData->args[0].toString(m->engine()->current));
else
value = Value::fromString(m->engine()->current, QString());
return Value::fromObject(m->engine()->newStringObject(value));
}
-Value StringCtor::call(Managed *m, const CallData &d)
+Value StringCtor::call(Managed *m, CallData *callData)
{
Value value;
- if (d.argc)
- value = Value::fromString(d.args[0].toString(m->engine()->current));
+ if (callData->argc)
+ value = Value::fromString(callData->args[0].toString(m->engine()->current));
else
value = Value::fromString(m->engine()->current, QString());
return value;
@@ -279,12 +280,15 @@ Value StringPrototype::method_charCodeAt(SimpleCallContext *context)
Value StringPrototype::method_concat(SimpleCallContext *context)
{
+ ValueScope scope(context);
+
QString value = getThisString(context, context->thisObject);
+ ScopedValue v(scope);
for (int i = 0; i < context->argumentCount; ++i) {
- Value v = __qmljs_to_string(context->arguments[i], context);
- assert(v.isString());
- value += v.stringValue()->toQString();
+ v = __qmljs_to_string(ValueRef(&context->arguments[i]), context);
+ assert(v->isString());
+ value += v->stringValue()->toQString();
}
return Value::fromString(context, value);
@@ -311,15 +315,17 @@ Value StringPrototype::method_indexOf(SimpleCallContext *context)
Value StringPrototype::method_lastIndexOf(SimpleCallContext *context)
{
+ ValueScope scope(context);
+
const QString value = getThisString(context, context->thisObject);
QString searchString;
if (context->argumentCount) {
- Value v = __qmljs_to_string(context->arguments[0], context);
+ Value v = __qmljs_to_string(ValueRef(&context->arguments[0]), context);
searchString = v.stringValue()->toQString();
}
- Value posArg = context->argumentCount > 1 ? context->arguments[1] : Value::undefinedValue();
+ ScopedValue posArg(scope, context->argumentCount > 1 ? context->arguments[1] : Value::undefinedValue());
double position = __qmljs_to_number(posArg);
if (std::isnan(position))
position = +qInf();
@@ -352,9 +358,9 @@ Value StringPrototype::method_match(SimpleCallContext *context)
Value regexp = context->argumentCount ? context->arguments[0] : Value::undefinedValue();
RegExpObject *rx = regexp.as<RegExpObject>();
if (!rx) {
- CALLDATA(1);
- d.args[0] = regexp;
- rx = context->engine->regExpCtor.asFunctionObject()->construct(d).as<RegExpObject>();
+ ScopedCallData callData(context->engine, 1);
+ callData->args[0] = regexp;
+ rx = context->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>();
}
if (!rx)
@@ -366,11 +372,11 @@ Value StringPrototype::method_match(SimpleCallContext *context)
// ### use the standard builtin function, not the one that might be redefined in the proto
FunctionObject *exec = context->engine->regExpClass->prototype->get(context->engine->newString(QStringLiteral("exec")), 0).asFunctionObject();
- CALLDATA(1);
- d.thisObject = Value::fromObject(rx);
- d.args[0] = Value::fromString(s);
+ ScopedCallData callData(context->engine, 1);
+ callData->thisObject = Value::fromObject(rx);
+ callData->args[0] = Value::fromString(s);
if (!global)
- return exec->call(d);
+ return exec->call(callData);
String *lastIndex = context->engine->newString(QStringLiteral("lastIndex"));
rx->put(lastIndex, Value::fromInt32(0));
@@ -379,7 +385,7 @@ Value StringPrototype::method_match(SimpleCallContext *context)
double previousLastIndex = 0;
uint n = 0;
while (1) {
- Value result = exec->call(d);
+ Value result = exec->call(callData);
if (result.isNull())
break;
assert(result.isObject());
@@ -505,8 +511,8 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
Value replaceValue = ctx->argument(1);
if (FunctionObject* searchCallback = replaceValue.asFunctionObject()) {
result.reserve(string.length() + 10*numStringMatches);
- CALLDATA(numCaptures + 2);
- d.thisObject = Value::undefinedValue();
+ ScopedCallData callData(ctx->engine, numCaptures + 2);
+ callData->thisObject = Value::undefinedValue();
int lastEnd = 0;
for (int i = 0; i < numStringMatches; ++i) {
for (int k = 0; k < numCaptures; ++k) {
@@ -516,15 +522,15 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
Value entry = Value::undefinedValue();
if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch)
entry = Value::fromString(ctx, string.mid(start, end - start));
- d.args[k] = entry;
+ callData->args[k] = entry;
}
uint matchStart = matchOffsets[i * numCaptures * 2];
Q_ASSERT(matchStart >= lastEnd);
uint matchEnd = matchOffsets[i * numCaptures * 2 + 1];
- d.args[numCaptures] = Value::fromUInt32(matchStart);
- d.args[numCaptures + 1] = Value::fromString(ctx, string);
+ callData->args[numCaptures] = Value::fromUInt32(matchStart);
+ callData->args[numCaptures + 1] = Value::fromString(ctx, string);
- Value replacement = searchCallback->call(d);
+ Value replacement = searchCallback->call(callData);
result += string.midRef(lastEnd, matchStart - lastEnd);
result += replacement.toString(ctx)->toQString();
lastEnd = matchEnd;
@@ -566,9 +572,9 @@ Value StringPrototype::method_search(SimpleCallContext *ctx)
Value regExpValue = ctx->argument(0);
RegExpObject *regExp = regExpValue.as<RegExpObject>();
if (!regExp) {
- CALLDATA(1);
- d.args[0] = regExpValue;
- regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->args[0] = regExpValue;
+ regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData);
regExp = regExpValue.as<RegExpObject>();
}
uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint));
@@ -783,7 +789,7 @@ Value StringPrototype::method_trim(SimpleCallContext *ctx)
if (ctx->thisObject.isNull() || ctx->thisObject.isUndefined())
ctx->throwTypeError();
- QString s = __qmljs_to_string(ctx->thisObject, ctx).stringValue()->toQString();
+ QString s = __qmljs_to_string(ValueRef(&ctx->thisObject), ctx).stringValue()->toQString();
const QChar *chars = s.constData();
int start, end;
for (start = 0; start < s.length(); ++start) {
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 38d6eeeac5..f9cf89e9d9 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -70,8 +70,8 @@ struct StringCtor: FunctionObject
{
StringCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4unwindhelper_arm_p.h b/src/qml/jsruntime/qv4unwindhelper_arm_p.h
index 6cfdce0e7d..e768544e11 100644
--- a/src/qml/jsruntime/qv4unwindhelper_arm_p.h
+++ b/src/qml/jsruntime/qv4unwindhelper_arm_p.h
@@ -79,7 +79,7 @@ static Function *lookupFunction(void *pc)
if (it == allFunctions.end())
return 0;
- quintptr codeStart = reinterpret_cast<quintptr>(removeThumbBit((void*)(*it)->code));
+ quintptr codeStart = reinterpret_cast<quintptr>(removeThumbBit((void*)(*it)->codePtr));
if (key < codeStart || key >= codeStart + (*it)->codeSize)
return 0;
return *it;
@@ -137,27 +137,27 @@ static unsigned write_prel31(unsigned *addr, void *ptr)
void UnwindHelper::deregisterFunction(Function *function)
{
QMutexLocker locker(&functionProtector);
- allFunctions.remove(reinterpret_cast<quintptr>(function->code));
+ allFunctions.remove(reinterpret_cast<quintptr>(function->codePtr));
}
void UnwindHelper::deregisterFunctions(const QVector<Function *> &functions)
{
QMutexLocker locker(&functionProtector);
foreach (Function *f, functions)
- allFunctions.remove(reinterpret_cast<quintptr>(f->code));
+ allFunctions.remove(reinterpret_cast<quintptr>(f->codePtr));
}
void UnwindHelper::registerFunction(Function *function)
{
QMutexLocker locker(&functionProtector);
- allFunctions.insert(reinterpret_cast<quintptr>(function->code), function);
+ allFunctions.insert(reinterpret_cast<quintptr>(function->codePtr), function);
}
void UnwindHelper::registerFunctions(const QVector<Function *> &functions)
{
QMutexLocker locker(&functionProtector);
foreach (Function *f, functions)
- allFunctions.insert(reinterpret_cast<quintptr>(f->code), f);
+ allFunctions.insert(reinterpret_cast<quintptr>(f->codePtr), f);
}
void UnwindHelper::prepareForUnwind(ExecutionContext *)
@@ -217,7 +217,7 @@ extern "C" Q_DECL_EXPORT void *__gnu_Unwind_Find_exidx(void *pc, int *entryCount
QV4::Function *function = QT_PREPEND_NAMESPACE(QV4::lookupFunction(pc));
if (function) {
*entryCount = 1;
- void * codeStart = QT_PREPEND_NAMESPACE(QV4::removeThumbBit((void*)function->code));
+ void * codeStart = QT_PREPEND_NAMESPACE(QV4::removeThumbBit((void*)function->codePtr));
// At the end of the function we store our synthetic exception table entry.
return (char *)codeStart + function->codeSize;
}
diff --git a/src/qml/jsruntime/qv4unwindhelper_dw2_p.h b/src/qml/jsruntime/qv4unwindhelper_dw2_p.h
index c53d20612c..03533ba526 100644
--- a/src/qml/jsruntime/qv4unwindhelper_dw2_p.h
+++ b/src/qml/jsruntime/qv4unwindhelper_dw2_p.h
@@ -127,7 +127,7 @@ UnwindInfo::~UnwindInfo()
static void ensureUnwindInfo(Function *f)
{
- if (!f->code)
+ if (!f->codePtr)
return; // Not a JIT generated function
ExecutableAllocator::ChunkOfPages *chunk = f->compilationUnit->chunkForFunction(f->compiledFunction->index);
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index a41262f12f..718b87d2c9 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -48,12 +48,47 @@
using namespace QV4;
+int Value::toInt32() const
+{
+ if (isConvertibleToInt())
+ return int_32;
+ double d;
+ if (isDouble())
+ d = dbl;
+ else
+ d = toNumber();
+
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
+
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Value::toInt32(d);
+}
+
+unsigned int Value::toUInt32() const
+{
+ if (isConvertibleToInt())
+ return (unsigned) int_32;
+ double d;
+ if (isDouble())
+ d = dbl;
+ else
+ d = toNumber();
+
+ const double D32 = 4294967296.0;
+ if (d >= 0 && d < D32)
+ return static_cast<uint>(d);
+ return toUInt32(d);
+}
+
int Value::toUInt16() const
{
if (isConvertibleToInt())
return (ushort)(uint)integerValue();
- double number = __qmljs_to_number(*this);
+ double number = toNumber();
double D16 = 65536.0;
if ((number >= 0 && number < D16))
@@ -79,12 +114,32 @@ double Value::toInteger() const
if (isConvertibleToInt())
return int_32;
- return Value::toInteger(__qmljs_to_number(*this));
+ return Value::toInteger(toNumber());
}
double Value::toNumber() const
{
- return __qmljs_to_number(*this);
+ QV4::Value v = *this;
+
+ redo:
+ switch (v.type()) {
+ case QV4::Value::Undefined_Type:
+ return std::numeric_limits<double>::quiet_NaN();
+ case QV4::Value::Null_Type:
+ return 0;
+ case QV4::Value::Boolean_Type:
+ return (v.booleanValue() ? 1. : 0.);
+ case QV4::Value::Integer_Type:
+ return v.int_32;
+ case QV4::Value::String_Type:
+ return __qmljs_string_to_number(v.toQString());
+ case QV4::Value::Object_Type: {
+ v = __qmljs_to_primitive(ValueRef::fromRawValue(this), QV4::NUMBER_HINT);
+ goto redo;
+ }
+ default: // double
+ return v.doubleValue();
+ }
}
QString Value::toQString() const
@@ -103,16 +158,18 @@ QString Value::toQString() const
return stringValue()->toQString();
case Value::Object_Type: {
ExecutionContext *ctx = objectValue()->internalClass->engine->current;
+ ValueScope scope(ctx);
try {
- Value prim = __qmljs_to_primitive(*this, STRING_HINT);
- if (prim.isPrimitive())
- return prim.toQString();
+ ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT));
+ if (prim->isPrimitive())
+ return prim->toQString();
} catch (Exception &e) {
e.accept(ctx);
try {
- Value prim = __qmljs_to_primitive(e.value(), STRING_HINT);
- if (prim.isPrimitive())
- return prim.toQString();
+ ScopedValue ex(scope, e.value());
+ ScopedValue prim(scope, __qmljs_to_primitive(ex, STRING_HINT));
+ if (prim->isPrimitive())
+ return prim->toQString();
} catch(Exception &e) {
e.accept(ctx);
}
@@ -216,9 +273,17 @@ String *Value::toString(ExecutionContext *ctx) const
{
if (isString())
return stringValue();
- return __qmljs_convert_to_string(ctx, *this);
+ return __qmljs_convert_to_string(ctx, ValueRef::fromRawValue(this));
+}
+
+Object *Value::toObject(ExecutionContext *ctx) const
+{
+ if (isObject())
+ return objectValue();
+ return __qmljs_convert_to_object(ctx, ValueRef::fromRawValue(this));
}
+
Value Value::property(ExecutionContext *ctx, String *name) const
{
return isObject() ? objectValue()->get(name) : undefinedValue();
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 73d5d0479d..8d6f26ea57 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-double __qmljs_to_number(const QV4::Value &value);
-Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const QV4::Value &value);
QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
inline Managed *Value::asManaged() const
@@ -193,48 +191,6 @@ inline bool Value::toBoolean() const
}
}
-inline Object *Value::toObject(ExecutionContext *ctx) const
-{
- if (isObject())
- return objectValue();
- return __qmljs_convert_to_object(ctx, *this);
-}
-
-inline int Value::toInt32() const
-{
- if (isConvertibleToInt())
- return int_32;
- double d;
- if (isDouble())
- d = dbl;
- else
- d = __qmljs_to_number(*this);
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Value::toInt32(d);
-}
-
-inline unsigned int Value::toUInt32() const
-{
- if (isConvertibleToInt())
- return (unsigned) int_32;
- double d;
- if (isDouble())
- d = dbl;
- else
- d = __qmljs_to_number(*this);
-
- const double D32 = 4294967296.0;
- if (d >= 0 && d < D32)
- return static_cast<uint>(d);
- return toUInt32(d);
-}
-
inline uint Value::asArrayIndex() const
{
if (isInteger() && int_32 >= 0)
@@ -320,10 +276,10 @@ inline ErrorObject *Value::asErrorObject() const
}
// ###
-inline Value Managed::construct(const CallData &d) {
+inline Value Managed::construct(CallData *d) {
return vtbl->construct(this, d);
}
-inline Value Managed::call(const CallData &d) {
+inline Value Managed::call(CallData *d) {
return vtbl->call(this, d);
}
@@ -380,6 +336,7 @@ public:
}
private:
+ friend struct ValueRef;
PersistentValuePrivate *d;
};
@@ -414,6 +371,7 @@ public:
void markOnce();
private:
+ friend struct ValueRef;
PersistentValuePrivate *d;
};
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index d5416105fa..92b0c75e8c 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -45,7 +45,7 @@
#include <private/qv4debugging_p.h>
#include <private/qv4exception_p.h>
#include <private/qv4math_p.h>
-
+#include <private/qv4scopedvalue_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -183,7 +183,9 @@ static inline QV4::Value *getValueRef(QV4::ExecutionContext *context,
return c->locals + index;
} else if (param.isTemp()) {
VMSTATS(paramIsTemp);
+#if !defined(QT_NO_DEBUG)
Q_ASSERT(param.index < stackSize);
+#endif
return stack + param.index;
} else if (param.isScopedLocal()) {
VMSTATS(paramIsScopedLocal);
@@ -281,29 +283,29 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(StoreName)
TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
- __qmljs_set_activation_property(context, runtimeStrings[instr.name], VALUE(instr.source));
+ __qmljs_set_activation_property(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(StoreName)
MOTH_BEGIN_INSTR(LoadElement)
- __qmljs_get_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_get_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
- __qmljs_set_element(context, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
+ __qmljs_set_element(context, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
- __qmljs_get_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name]);
+ __qmljs_get_property(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.name]);
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(StoreProperty)
- __qmljs_set_property(context, VALUE(instr.base), runtimeStrings[instr.name], VALUE(instr.source));
+ __qmljs_set_property(context, VALUEPTR(instr.base), runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(Push)
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
- stack = static_cast<QV4::Value *>(alloca(stackSize * sizeof(QV4::Value)));
+ stack = context->engine->stackPush(stackSize);
memset(stack, 0, stackSize * sizeof(QV4::Value));
MOTH_END_INSTR(Push)
@@ -318,33 +320,45 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
}
}
#endif // DO_TRACE_INSTR
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_value(context, VALUEPTR(instr.result), /*thisObject*/0, VALUE(instr.dest), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_call_value(context, VALUEPTR(instr.result), VALUEPTR(instr.dest), callData);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(instr.name->toQString()), instr.args, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ __qmljs_call_property(context, QV4::ValueRef::fromRawValue(VALUEPTR(instr.result)), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallElement)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ __qmljs_call_element(context, VALUEPTR(instr.result), VALUEPTR(instr.index), callData);
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallBuiltinThrow)
- __qmljs_throw(context, VALUE(instr.arg));
+ __qmljs_throw(context, VALUEPTR(instr.arg));
MOTH_END_INSTR(CallBuiltinThrow)
MOTH_BEGIN_INSTR(EnterTry)
@@ -358,7 +372,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
ex.accept(context);
VALUE(instr.exceptionVar) = ex.value();
try {
- QV4::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(runtimeStrings[instr.exceptionVarName], ex.value(), context);
+ QV4::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(runtimeStrings[instr.exceptionVarName], VALUEPTR(instr.exceptionVar), context);
const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
run(catchContext, catchCode, stack, stackSize);
code = catchCode;
@@ -380,7 +394,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinFinishTry)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
- context = __qmljs_builtin_push_with_scope(VALUE(instr.arg), context);
+ context = __qmljs_builtin_push_with_scope(VALUEPTR(instr.arg), context);
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
@@ -388,19 +402,19 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
- __qmljs_foreach_iterator_object(context, VALUEPTR(instr.result), VALUE(instr.arg));
+ __qmljs_foreach_iterator_object(context, VALUEPTR(instr.result), VALUEPTR(instr.arg));
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
- __qmljs_foreach_next_property_name(VALUEPTR(instr.result), VALUE(instr.arg));
+ __qmljs_foreach_next_property_name(VALUEPTR(instr.result), VALUEPTR(instr.arg));
MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
- __qmljs_delete_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_delete_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinDeleteMember)
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
- __qmljs_delete_subscript(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_delete_subscript(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
@@ -408,11 +422,11 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinDeleteName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
- __qmljs_builtin_typeof_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_builtin_typeof_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
- __qmljs_builtin_typeof_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_builtin_typeof_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
@@ -420,15 +434,15 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinTypeofName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
- __qmljs_builtin_typeof(context, VALUEPTR(instr.result), VALUE(instr.value));
+ __qmljs_builtin_typeof(context, VALUEPTR(instr.result), VALUEPTR(instr.value));
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinPostIncMember)
- __qmljs_builtin_post_increment_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_builtin_post_increment_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinPostIncSubscript)
- __qmljs_builtin_post_increment_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUEPTR(instr.index));
+ __qmljs_builtin_post_increment_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinPostIncName)
@@ -440,11 +454,11 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinPostDecMember)
- __qmljs_builtin_post_decrement_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_builtin_post_decrement_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinPostDecSubscript)
- __qmljs_builtin_post_decrement_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_builtin_post_decrement_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinPostDecName)
@@ -460,11 +474,11 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinDeclareVar)
MOTH_BEGIN_INSTR(CallBuiltinDefineGetterSetter)
- __qmljs_builtin_define_getter_setter(context, VALUE(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.getter), VALUEPTR(instr.setter));
+ __qmljs_builtin_define_getter_setter(context, VALUEPTR(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.getter), VALUEPTR(instr.setter));
MOTH_END_INSTR(CallBuiltinDefineGetterSetter)
MOTH_BEGIN_INSTR(CallBuiltinDefineProperty)
- __qmljs_builtin_define_property(context, VALUE(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.value));
+ __qmljs_builtin_define_property(context, VALUEPTR(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.value));
MOTH_END_INSTR(CallBuiltinDefineProperty)
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
@@ -483,22 +497,31 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
MOTH_BEGIN_INSTR(CreateValue)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_value(context, VALUEPTR(instr.result), VALUE(instr.func), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_value(context, VALUEPTR(instr.result), VALUEPTR(instr.func), callData);
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_property(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, args = %d, argc = %d", instr.name->toQString().toUtf8().constData(), instr.args, instr.argc);
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(Jump)
@@ -506,22 +529,22 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(Jump)
MOTH_BEGIN_INSTR(CJump)
- uint cond = __qmljs_to_boolean(VALUE(instr.condition));
+ uint cond = __qmljs_to_boolean(VALUEPTR(instr.condition));
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
if (cond)
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(CJump)
MOTH_BEGIN_INSTR(Unop)
- instr.alu(VALUEPTR(instr.result), VALUE(instr.source));
+ instr.alu(QV4::ValueRef::fromRawValue(VALUEPTR(instr.result)), QV4::ValueRef::fromRawValue(VALUEPTR(instr.source)));
MOTH_END_INSTR(Unop)
MOTH_BEGIN_INSTR(Binop)
- instr.alu(VALUEPTR(instr.result), VALUE(instr.lhs), VALUE(instr.rhs));
+ instr.alu(VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs));
MOTH_END_INSTR(Binop)
MOTH_BEGIN_INSTR(BinopContext)
- instr.alu(context, VALUEPTR(instr.result), VALUE(instr.lhs), VALUE(instr.rhs));
+ instr.alu(context, VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs));
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(AddNumberParams)
@@ -552,6 +575,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(SubNumberParams)
MOTH_BEGIN_INSTR(Ret)
+ context->engine->stackPop(stackSize);
QV4::Value &result = VALUE(instr.result);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
return result;
@@ -563,21 +587,21 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(InplaceElementOp)
instr.alu(context,
- VALUE(instr.base),
- VALUE(instr.index),
- VALUE(instr.source));
+ VALUEPTR(instr.base),
+ VALUEPTR(instr.index),
+ VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceElementOp)
MOTH_BEGIN_INSTR(InplaceMemberOp)
instr.alu(context,
- VALUE(instr.base),
+ VALUEPTR(instr.base),
runtimeStrings[instr.member],
- VALUE(instr.source));
+ VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceMemberOp)
MOTH_BEGIN_INSTR(InplaceNameOp)
TRACE(name, "%s", instr.name->toQString().toUtf8().constData());
- instr.alu(context, runtimeStrings[instr.name], VALUE(instr.source));
+ instr.alu(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceNameOp)
#ifdef MOTH_THREADED_INTERPRETER
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index a70b9064d9..475e69cd77 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -62,6 +62,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
+#include <private/qv4scopedvalue_p.h>
#include <QStack>
#include <QStringList>
@@ -1240,12 +1241,12 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (!valuemap.isEmpty()) {
QQmlComponentExtension *e = componentExtension(v8engine);
- QV4::Value f = QV4::Script::evaluate(QV8Engine::getV4(v8engine), QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject());
- CALLDATA(2);
- d.thisObject = QV4::Value::fromObject(v4engine->globalObject);
- d.args[0] = object;
- d.args[1] = valuemap;
- f.asFunctionObject()->call(d);
+ QV4::Value f = QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject());
+ QV4::ScopedCallData callData(v4engine, 2);
+ callData->thisObject = QV4::Value::fromObject(v4engine->globalObject);
+ callData->args[0] = object;
+ callData->args[1] = valuemap;
+ f.asFunctionObject()->call(callData);
}
d->completeCreate();
@@ -1388,11 +1389,11 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu
if (!valuemap.isEmpty()) {
QQmlComponentExtension *e = componentExtension(v8engine);
QV4::Value f = QV4::Script::evaluate(QV8Engine::getV4(v8engine), QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject());
- CALLDATA(2);
- d.thisObject = QV4::Value::fromObject(v4engine->globalObject);
- d.args[0] = object;
- d.args[1] = valuemap;
- f.asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(v4engine, 2);
+ callData->thisObject = QV4::Value::fromObject(v4engine->globalObject);
+ callData->args[0] = object;
+ callData->args[1] = valuemap;
+ f.asFunctionObject()->call(callData);
}
}
@@ -1487,11 +1488,11 @@ void QmlIncubatorObject::setInitialState(QObject *o)
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
QV4::Value f = QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject());
- CALLDATA(2);
- d.thisObject = QV4::Value::fromObject(v4->globalObject);
- d.args[0] = QV4::QObjectWrapper::wrap(v4, o);
- d.args[1] = valuemap;
- f.asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(v4, 2);
+ callData->thisObject = QV4::Value::fromObject(v4->globalObject);
+ callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
+ callData->args[1] = valuemap;
+ f.asFunctionObject()->call(callData);
}
}
@@ -1524,10 +1525,10 @@ void QmlIncubatorObject::statusChanged(Status s)
if (QV4::FunctionObject *f = callback.asFunctionObject()) {
QV4::ExecutionContext *ctx = f->engine()->current;
try {
- CALLDATA(1);
- d.thisObject = QV4::Value::fromObject(this);
- d.args[0] = QV4::Value::fromUInt32(s);
- f->call(d);
+ QV4::ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = QV4::Value::fromObject(this);
+ callData->args[0] = QV4::Value::fromUInt32(s);
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 41be44a0a7..2974bbcfbe 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -47,6 +47,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -125,8 +126,7 @@ QV4::Value
QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
const QV4::Value &function, bool *isUndefined)
{
- QV4::Value args[QV4::Global::ReservedArgumentCount];
- return evaluate(context, function, 0, args, isUndefined);
+ return evaluate(context, function, 0, 0, isUndefined);
}
QV4::Value
@@ -173,11 +173,10 @@ QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
This = value;
}
- QV4::CallData d;
- d.thisObject = This;
- d.args = args;
- d.argc = argc;
- result = function.asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(v4, argc);
+ callData->thisObject = This;
+ memcpy(callData->args, args, argc*sizeof(QV4::Value));
+ result = function.asFunctionObject()->call(callData);
if (isUndefined)
*isUndefined = result.isUndefined();
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index d1ecfdc52d..cf1b5ffd18 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1611,10 +1611,14 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
{
if (engine) {
return engine->rawMetaObjectForType(userType);
- } else {
- QQmlType *type = QQmlMetaType::qmlType(userType);
- return QQmlMetaObject(type?type->baseMetaObject():0);
}
+ QQmlType *type = QQmlMetaType::qmlType(userType);
+ if (type)
+ return QQmlMetaObject(type->baseMetaObject());
+ QMetaType metaType(userType);
+ if ((metaType.flags() & QMetaType::PointerToQObject) && metaType.metaObject())
+ return metaType.metaObject();
+ return QQmlMetaObject((QObject*)0);
}
/*!
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index d10af391f5..a1385e06fc 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -124,7 +124,7 @@ static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *en
engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType)
: QQmlMetaType::typeCategory(propType);
- if (cat == QQmlMetaType::Object)
+ if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject)
flags |= QQmlPropertyData::IsQObjectDerived;
else if (cat == QQmlMetaType::List)
flags |= QQmlPropertyData::IsQList;
@@ -1553,7 +1553,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
} else {
method = builder.addSlot(signature);
}
- method.setAccess(QMetaMethod::Protected);
+ method.setAccess(QMetaMethod::Public);
if (arguments && arguments->names)
method.setParameterNames(*arguments->names);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 3d2d54ccfa..0079b9580f 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -55,6 +55,7 @@
#include <private/qv4object_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4functionobject_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -926,16 +927,16 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QQmlVMEMetaData::MethodData *data = metaData->methodData() + id;
- CALLDATA(data->parameterCount);
- d.thisObject = ep->v8engine()->global();
+ QV4::ScopedCallData callData(function->engine(), data->parameterCount);
+ callData->thisObject = ep->v8engine()->global();
for (int ii = 0; ii < data->parameterCount; ++ii)
- d.args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
+ callData->args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
QV4::Value result = QV4::Value::undefinedValue();
QV4::ExecutionContext *ctx = function->engine()->current;
try {
- result = function->call(d);
+ result = function->call(callData);
if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
} catch (QV4::Exception &e) {
e.accept(ctx);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 211383ae58..ddc7a4894b 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -53,6 +53,7 @@
#include <private/qv4engine_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qqmlcontextwrapper_p.h>
+#include <private/qv4scopedvalue_p.h>
#include <QtCore/qobject.h>
#include <QtQml/qjsvalue.h>
@@ -1481,9 +1482,9 @@ void QQmlXMLHttpRequest::dispatchCallback(const Value &me)
QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
if (callingContext) {
- CALLDATA(0);
- d.thisObject = activationObject;
- callback->call(d);
+ QV4::ScopedCallData callData(v4, 0);
+ callData->thisObject = activationObject;
+ callback->call(callData);
}
// if the callingContext object is no longer valid, then it has been
@@ -1563,7 +1564,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
if (c->proto)
c->proto->mark();
}
- static Value construct(Managed *that, const QV4::CallData &)
+ static Value construct(Managed *that, QV4::CallData *)
{
QQmlXMLHttpRequestCtor *ctor = that->as<QQmlXMLHttpRequestCtor>();
if (!ctor)
@@ -1576,7 +1577,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
return Value::fromObject(w);
}
- static Value call(Managed *, const QV4::CallData &) {
+ static Value call(Managed *, QV4::CallData *) {
return Value::undefinedValue();
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 8a636cdb99..2321e27bc6 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1184,10 +1184,10 @@ struct BindingFunction : public QV4::FunctionObject
bindingKeyFlag = true;
}
- static Value call(Managed *that, const CallData &d)
+ static Value call(Managed *that, CallData *callData)
{
BindingFunction *This = static_cast<BindingFunction*>(that);
- return This->originalFunction->call(d);
+ return This->originalFunction->call(callData);
}
static void markObjects(Managed *that)
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 117fea272c..5b43dd6192 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -57,6 +57,7 @@
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
+#include <private/qv4scopedvalue_p.h>
#include "qv4domerrors_p.h"
#include "qv4sqlerrors_p.h"
@@ -310,6 +311,8 @@ QV4::Value QV8Engine::fromVariant(const QVariant &variant)
a->arrayData[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii));
a->setArrayLengthUnchecked(list.count());
return QV4::Value::fromObject(a);
+ } else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) {
+ return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(ptr));
}
bool objOk;
@@ -440,10 +443,10 @@ void QV8Engine::initializeGlobal()
void QV8Engine::freezeObject(const QV4::Value &value)
{
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = QV4::Value::fromObject(m_v4Engine->globalObject);
- m_freezeObject.value().asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(m_v4Engine, 1);
+ callData->args[0] = value;
+ callData->thisObject = QV4::Value::fromObject(m_v4Engine->globalObject);
+ m_freezeObject.value().asFunctionObject()->call(callData);
}
void QV8Engine::gc()
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 9c486d9809..8f724fa2eb 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -136,13 +136,13 @@ private:
QQmlV4Function(const QQmlV4Function &);
QQmlV4Function &operator=(const QQmlV4Function &);
- QQmlV4Function(int length, QV4::Value *args,
+ QQmlV4Function(int length, const QV4::Value *args,
QV4::Value *rv, const QV4::Value &global,
QQmlContextData *c, QV8Engine *e)
: argc(length), args(args), retVal(rv), global(global), ctx(c), e(e) {}
int argc;
- QV4::Value *args;
+ const QV4::Value *args;
QV4::Value *retVal;
QV4::Value global;
QQmlContextData *ctx;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index b1b4862b18..bc52da6151 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -75,20 +75,20 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
isBuiltinFunction = true;
}
- static QV4::Value construct(QV4::Managed *m, const QV4::CallData &)
+ static QV4::Value construct(QV4::Managed *m, QV4::CallData *)
{
m->engine()->current->throwTypeError();
return QV4::Value::undefinedValue();
}
- static QV4::Value call(QV4::Managed *that, const QV4::CallData &d)
+ static QV4::Value call(QV4::Managed *that, QV4::CallData *callData)
{
DelegateModelGroupFunction *f = static_cast<DelegateModelGroupFunction *>(that);
- QQmlDelegateModelItemObject *o = d.thisObject.as<QQmlDelegateModelItemObject>();
+ QQmlDelegateModelItemObject *o = callData->thisObject.as<QQmlDelegateModelItemObject>();
if (!o)
that->engine()->current->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- QV4::Value v = d.argc ? d.args[0] : QV4::Value::undefinedValue();
+ QV4::Value v = callData->argc ? callData->args[0] : QV4::Value::undefinedValue();
return f->code(o->item, f->flag, v);
}
};
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 8822eaecd0..26514ac6db 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -65,6 +65,7 @@
#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -233,10 +234,10 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
QV4::Value function = QV4::Value::fromObject(m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, m_v4Engine->newString(QStringLiteral("sendMessage")),
QQuickWorkerScriptEnginePrivate::sendMessage));
- CALLDATA(1);
- d.args[0] = function;
- d.thisObject = global();
- createsend = createsendconstructor->call(d);
+ QV4::ScopedCallData callData(m_v4Engine, 1);
+ callData->args[0] = function;
+ callData->thisObject = global();
+ createsend = createsendconstructor->call(callData);
}
// Requires handle and context scope
@@ -246,10 +247,10 @@ QV4::Value QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id)
QV4::Value v = QV4::Value::undefinedValue();
QV4::ExecutionContext *ctx = f->internalClass->engine->current;
try {
- CALLDATA(1);
- d.args[0] = QV4::Value::fromInt32(id);
- d.thisObject = global();
- v = f->call(d);
+ QV4::ScopedCallData callData(m_v4Engine, 1);
+ callData->args[0] = QV4::Value::fromInt32(id);
+ callData->thisObject = global();
+ v = f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
v = e.value();
@@ -351,11 +352,11 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
QV4::ExecutionContext *ctx = f->internalClass->engine->current;
try {
- CALLDATA(2);
- d.thisObject = workerEngine->global();
- d.args[0] = script->object.value();
- d.args[1] = value;
- f->call(d);
+ QV4::ScopedCallData callData(ctx->engine, 2);
+ callData->thisObject = workerEngine->global();
+ callData->args[0] = script->object.value();
+ callData->args[1] = value;
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 2538cad211..52281a4fbc 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -54,6 +54,7 @@
#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -663,10 +664,10 @@ void QQuickCanvasItem::updatePolish()
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(qmlEngine(this));
QV4::FunctionObject *f = animationCallbacks.value(key).value().asFunctionObject();
- CALLDATA(1);
- d.thisObject = QV4::QObjectWrapper::wrap(v4, this);
- d.args[0] = QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t());
- f->call(d);
+ QV4::ScopedCallData callData(v4, 1);
+ callData->thisObject = QV4::QObjectWrapper::wrap(v4, this);
+ callData->args[0] = QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t());
+ f->call(callData);
}
}
else {
diff --git a/src/quick/items/qquickclipnode.cpp b/src/quick/items/qquickclipnode.cpp
index f20ca4a42c..5b3fe19595 100644
--- a/src/quick/items/qquickclipnode.cpp
+++ b/src/quick/items/qquickclipnode.cpp
@@ -51,6 +51,7 @@ QQuickDefaultClipNode::QQuickDefaultClipNode(const QRectF &rect)
, m_dirty_geometry(true)
, m_geometry(QSGGeometry::defaultAttributes_Point2D(), 0)
{
+ Q_UNUSED(m_reserved);
setGeometry(&m_geometry);
setIsRectangular(true);
}
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index f145ce259f..0ae26cb5c3 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -46,7 +46,9 @@
#include <private/qquickitemchangelistener_p.h>
#include <private/qv8engine_p.h>
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmimedata.h>
#include <QtQml/qqmlinfo.h>
+#include <QtGui/qdrag.h>
#include <QtGui/qevent.h>
#ifndef QT_NO_DRAGANDDROP
@@ -72,6 +74,7 @@ public:
, itemMoved(false)
, eventQueued(false)
, overrideActions(false)
+ , dragType(QQuickDrag::Internal)
{
}
@@ -83,8 +86,8 @@ public:
void deliverMoveEvent();
void deliverLeaveEvent();
void deliverEvent(QQuickWindow *window, QEvent *event);
- void start() { start(supportedActions); }
void start(Qt::DropActions supportedActions);
+ Qt::DropAction startDrag(Qt::DropActions supportedActions);
void setTarget(QQuickItem *item);
QQuickDragGrabber dragGrabber;
@@ -105,6 +108,8 @@ public:
bool overrideActions : 1;
QPointF hotSpot;
QStringList keys;
+ QVariantMap externalMimeData;
+ QQuickDrag::DragType dragType;
};
/*!
@@ -272,7 +277,10 @@ QQuickDragAttached::~QQuickDragAttached()
This property holds whether a drag event sequence is currently active.
- Setting this property to true will send a QDragEnter event to the scene
+ Binding this property to the active property of \l MouseArea::drag will
+ cause \l startDrag to be called when the user starts dragging.
+
+ Setting this property to true will also send a QDragEnter event to the scene
with the item's current position. Setting it to false will send a
QDragLeave event.
@@ -292,8 +300,18 @@ void QQuickDragAttached::setActive(bool active)
if (d->active != active) {
if (d->inEvent)
qmlInfo(this) << "active cannot be changed from within a drag event handler";
- else if (active)
- d->start(d->supportedActions);
+ else if (active) {
+ if (d->dragType == QQuickDrag::Internal) {
+ d->start(d->supportedActions);
+ }
+ else if (d->dragType == QQuickDrag::Automatic) {
+ // There are different semantics than start() since startDrag()
+ // may be called after an internal drag is already started.
+ active = true;
+ emit activeChanged();
+ d->startDrag(d->supportedActions);
+ }
+ }
else
cancel();
}
@@ -411,6 +429,28 @@ void QQuickDragAttached::setKeys(const QStringList &keys)
}
/*!
+ \qmlattachedproperty stringlist QtQuick2::Drag::mimeData
+ \since QtQuick 2.2
+
+ This property holds a map of mimeData that is used during startDrag.
+*/
+
+QVariantMap QQuickDragAttached::mimeData() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->externalMimeData;
+}
+
+void QQuickDragAttached::setMimeData(const QVariantMap &mimeData)
+{
+ Q_D(QQuickDragAttached);
+ if (d->externalMimeData != mimeData) {
+ d->externalMimeData = mimeData;
+ emit mimeDataChanged();
+ }
+}
+
+/*!
\qmlattachedproperty flags QtQuick2::Drag::supportedActions
This property holds return values of Drag.drop() supported by the drag source.
@@ -465,6 +505,42 @@ void QQuickDragAttached::setProposedAction(Qt::DropAction action)
}
}
+/*!
+ \qmlattachedproperty enumeration QtQuick2::Drag::dragType
+ \since QtQuick 2.2
+
+ This property indicates whether to automatically start drags, do nothing, or
+ to use backwards compatible internal drags. The default is to use backwards
+ compatible internal drags.
+
+ A drag can also be started manually using \l startDrag.
+
+ \list
+ \li Drag.None - do not start drags automatically
+ \li Drag.Automatic - start drags automatically
+ \li Drag.Internal (default) - start backwards compatible drags automatically
+ \endlist
+
+ When using \l Drag.Automatic you should also define \l mimeData and bind the
+ \active property to the active property of \l MouseArea.drag.
+
+ */
+
+QQuickDrag::DragType QQuickDragAttached::dragType() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->dragType;
+}
+
+void QQuickDragAttached::setDragType(QQuickDrag::DragType dragType)
+{
+ Q_D(QQuickDragAttached);
+ if (d->dragType != dragType) {
+ d->dragType = dragType;
+ emit dragTypeChanged();
+ }
+}
+
void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
{
Q_Q(QQuickDragAttached);
@@ -496,7 +572,8 @@ void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
/*!
\qmlattachedmethod void QtQuick2::Drag::start(flags supportedActions)
- Starts sending drag events.
+ Starts sending drag events. Used for starting old-style internal drags. \l startDrag is the
+ new-style, preferred method of starting drags.
The optional \a supportedActions argument can be used to override the \l supportedActions
property for the started sequence.
@@ -616,6 +693,223 @@ void QQuickDragAttached::cancel()
emit activeChanged();
}
+/*!
+ \qmlsignal QtQuick2::DropArea::onDragStarted()
+
+ This handler is called when a drag is started with the \l startDrag method
+ or when it is started automatically using the \l dragType property.
+ */
+
+/*!
+ \qmlsignal QtQuick2::DropArea::onDragFinished(DropAction action)
+
+ This handler is called when a drag finishes and the drag was started with the
+ \l startDrag method or started automatically using the \l dragType property.
+ */
+
+Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedActions)
+{
+ Q_Q(QQuickDragAttached);
+
+ QDrag *drag = new QDrag(q);
+ QMimeData *mimeData = new QMimeData();
+
+ Q_FOREACH (const QString &key, externalMimeData.keys()) {
+ mimeData->setData(key, externalMimeData[key].toString().toUtf8());
+ }
+
+ drag->setMimeData(mimeData);
+
+ // TODO: how to handle drag image?
+ // drag->setPixmap(iconPixmap);
+
+ emit q->dragStarted();
+
+ Qt::DropAction dropAction = drag->exec(supportedActions);
+
+ delete drag;
+
+ deliverLeaveEvent();
+
+ if (target) {
+ target = 0;
+ emit q->targetChanged();
+ }
+
+ emit q->dragFinished(dropAction);
+
+ active = false;
+ emit q->activeChanged();
+
+ return dropAction;
+}
+
+
+/*!
+ \qmlattachedmethod void QtQuick2::Drag::startDrag(flags supportedActions)
+
+ Starts sending drag events.
+
+ The optional \a supportedActions argument can be used to override the \l supportedActions
+ property for the started sequence.
+*/
+
+void QQuickDragAttached::startDrag(QQmlV4Function *args)
+{
+ Q_D(QQuickDragAttached);
+
+ if (d->inEvent) {
+ qmlInfo(this) << "startDrag() cannot be called from within a drag event handler";
+ return;
+ }
+
+ if (!d->active) {
+ qmlInfo(this) << "startDrag() drag must be active";
+ return;
+ }
+
+ Qt::DropActions supportedActions = d->supportedActions;
+
+ // check arguments for supportedActions
+ if (args->length() >= 1) {
+ QV4::Value v = (*args)[0];
+ if (v.isInt32()) {
+ supportedActions = Qt::DropActions(v.integerValue());
+ }
+ }
+
+ Qt::DropAction dropAction = d->startDrag(supportedActions);
+
+ args->setReturnValue(QV4::Value::fromInt32(dropAction));
+}
+
+QQuickDrag::QQuickDrag(QObject *parent)
+: QObject(parent), _target(0), _axis(XAndYAxis), _xmin(-FLT_MAX),
+_xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false)
+{
+}
+
+QQuickDrag::~QQuickDrag()
+{
+}
+
+QQuickItem *QQuickDrag::target() const
+{
+ return _target;
+}
+
+void QQuickDrag::setTarget(QQuickItem *t)
+{
+ if (_target == t)
+ return;
+ _target = t;
+ emit targetChanged();
+}
+
+void QQuickDrag::resetTarget()
+{
+ if (_target == 0)
+ return;
+ _target = 0;
+ emit targetChanged();
+}
+
+QQuickDrag::Axis QQuickDrag::axis() const
+{
+ return _axis;
+}
+
+void QQuickDrag::setAxis(QQuickDrag::Axis a)
+{
+ if (_axis == a)
+ return;
+ _axis = a;
+ emit axisChanged();
+}
+
+qreal QQuickDrag::xmin() const
+{
+ return _xmin;
+}
+
+void QQuickDrag::setXmin(qreal m)
+{
+ if (_xmin == m)
+ return;
+ _xmin = m;
+ emit minimumXChanged();
+}
+
+qreal QQuickDrag::xmax() const
+{
+ return _xmax;
+}
+
+void QQuickDrag::setXmax(qreal m)
+{
+ if (_xmax == m)
+ return;
+ _xmax = m;
+ emit maximumXChanged();
+}
+
+qreal QQuickDrag::ymin() const
+{
+ return _ymin;
+}
+
+void QQuickDrag::setYmin(qreal m)
+{
+ if (_ymin == m)
+ return;
+ _ymin = m;
+ emit minimumYChanged();
+}
+
+qreal QQuickDrag::ymax() const
+{
+ return _ymax;
+}
+
+void QQuickDrag::setYmax(qreal m)
+{
+ if (_ymax == m)
+ return;
+ _ymax = m;
+ emit maximumYChanged();
+}
+
+bool QQuickDrag::active() const
+{
+ return _active;
+}
+
+void QQuickDrag::setActive(bool drag)
+{
+ if (_active == drag)
+ return;
+ _active = drag;
+ emit activeChanged();
+}
+
+bool QQuickDrag::filterChildren() const
+{
+ return _filterChildren;
+}
+
+void QQuickDrag::setFilterChildren(bool filter)
+{
+ if (_filterChildren == filter)
+ return;
+ _filterChildren = filter;
+ emit filterChildrenChanged();
+}
+
+QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickDragAttached(obj);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DRAGANDDROP
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 3680fd5754..098fcc61b9 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -143,18 +143,90 @@ private:
};
class QQmlV4Function;
+class QQuickDragAttached;
+class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Axis DragType)
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
+ Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
+ Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
+ Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
+ Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
+ Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
+ //### consider drag and drop
+
+public:
+ QQuickDrag(QObject *parent=0);
+ ~QQuickDrag();
+
+ enum DragType { None, Automatic, Internal };
+
+ QQuickItem *target() const;
+ void setTarget(QQuickItem *target);
+ void resetTarget();
+
+ enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
+ Axis axis() const;
+ void setAxis(Axis);
+
+ qreal xmin() const;
+ void setXmin(qreal);
+ qreal xmax() const;
+ void setXmax(qreal);
+ qreal ymin() const;
+ void setYmin(qreal);
+ qreal ymax() const;
+ void setYmax(qreal);
+
+ bool active() const;
+ void setActive(bool);
+
+ bool filterChildren() const;
+ void setFilterChildren(bool);
+
+ static QQuickDragAttached *qmlAttachedProperties(QObject *obj);
+
+Q_SIGNALS:
+ void targetChanged();
+ void axisChanged();
+ void minimumXChanged();
+ void maximumXChanged();
+ void minimumYChanged();
+ void maximumYChanged();
+ void activeChanged();
+ void filterChildrenChanged();
+
+private:
+ QQuickItem *_target;
+ Axis _axis;
+ qreal _xmin;
+ qreal _xmax;
+ qreal _ymin;
+ qreal _ymax;
+ bool _active : 1;
+ bool _filterChildren: 1;
+ Q_DISABLE_COPY(QQuickDrag)
+};
class QQuickDragAttachedPrivate;
class QQuickDragAttached : public QObject
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickDragAttached)
+
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
+ Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged)
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
Q_PROPERTY(Qt::DropAction proposedAction READ proposedAction WRITE setProposedAction NOTIFY proposedActionChanged)
+ Q_PROPERTY(QQuickDrag::DragType dragType READ dragType WRITE setDragType NOTIFY dragTypeChanged)
public:
QQuickDragAttached(QObject *parent);
~QQuickDragAttached();
@@ -174,36 +246,47 @@ public:
QStringList keys() const;
void setKeys(const QStringList &keys);
+ QVariantMap mimeData() const;
+ void setMimeData(const QVariantMap &mimeData);
+
Qt::DropActions supportedActions() const;
void setSupportedActions(Qt::DropActions actions);
Qt::DropAction proposedAction() const;
void setProposedAction(Qt::DropAction action);
+ QQuickDrag::DragType dragType() const;
+ void setDragType(QQuickDrag::DragType dragType);
+
Q_INVOKABLE int drop();
bool event(QEvent *event);
public Q_SLOTS:
void start(QQmlV4Function *);
+ void startDrag(QQmlV4Function *);
void cancel();
Q_SIGNALS:
+ void dragStarted();
+ void dragFinished(Qt::DropAction dropAction);
+
void activeChanged();
void sourceChanged();
void targetChanged();
void hotSpotChanged();
void keysChanged();
+ void mimeDataChanged();
void supportedActionsChanged();
void proposedActionChanged();
-
-private:
- Q_DECLARE_PRIVATE(QQuickDragAttached)
+ void dragTypeChanged();
};
-
QT_END_NAMESPACE
+QML_DECLARE_TYPE(QQuickDrag)
+QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
+
#endif // QT_NO_DRAGANDDROP
#endif
diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp
index f453c42e5b..09dc7eeebb 100644
--- a/src/quick/items/qquickdroparea.cpp
+++ b/src/quick/items/qquickdroparea.cpp
@@ -77,11 +77,12 @@ public:
QPointF dragPosition;
QQuickDropAreaDrag *drag;
QPointer<QObject> source;
- QPointer<QMimeData> mimeData;
+ bool containsDrag;
};
QQuickDropAreaPrivate::QQuickDropAreaPrivate()
: drag(0)
+ , containsDrag(false)
{
}
@@ -133,7 +134,7 @@ QQuickDropArea::~QQuickDropArea()
bool QQuickDropArea::containsDrag() const
{
Q_D(const QQuickDropArea);
- return d->mimeData;
+ return d->containsDrag;
}
/*!
@@ -217,7 +218,7 @@ qreal QQuickDropAreaDrag::y() const
void QQuickDropArea::dragMoveEvent(QDragMoveEvent *event)
{
Q_D(QQuickDropArea);
- if (!d->mimeData)
+ if (!d->containsDrag)
return;
d->dragPosition = event->pos();
@@ -259,28 +260,27 @@ void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event)
{
Q_D(QQuickDropArea);
const QMimeData *mimeData = event->mimeData();
- if (!d->effectiveEnable || d->mimeData || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
+ if (!d->effectiveEnable || d->containsDrag || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
return;
d->dragPosition = event->pos();
event->accept();
+
QQuickDropEvent dragTargetEvent(d, event);
emit entered(&dragTargetEvent);
- if (event->isAccepted()) {
- d->mimeData = const_cast<QMimeData *>(mimeData);
- if (QQuickDragMimeData *dragMime = qobject_cast<QQuickDragMimeData *>(d->mimeData))
- d->source = dragMime->source();
- else
- d->source = event->source();
- d->dragPosition = event->pos();
- if (d->drag) {
- emit d->drag->positionChanged();
- emit d->drag->sourceChanged();
- }
- emit containsDragChanged();
+ d->containsDrag = true;
+ if (QQuickDragMimeData *dragMime = qobject_cast<QQuickDragMimeData *>(const_cast<QMimeData *>(mimeData)))
+ d->source = dragMime->source();
+ else
+ d->source = event->source();
+ d->dragPosition = event->pos();
+ if (d->drag) {
+ emit d->drag->positionChanged();
+ emit d->drag->sourceChanged();
}
+ emit containsDragChanged();
}
/*!
@@ -292,12 +292,12 @@ void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event)
void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *)
{
Q_D(QQuickDropArea);
- if (!d->mimeData)
+ if (!d->containsDrag)
return;
emit exited();
- d->mimeData = 0;
+ d->containsDrag = false;
d->source = 0;
emit containsDragChanged();
if (d->drag)
@@ -314,13 +314,13 @@ void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *)
void QQuickDropArea::dropEvent(QDropEvent *event)
{
Q_D(QQuickDropArea);
- if (!d->mimeData)
+ if (!d->containsDrag)
return;
QQuickDropEvent dragTargetEvent(d, event);
emit dropped(&dragTargetEvent);
- d->mimeData = 0;
+ d->containsDrag = false;
d->source = 0;
emit containsDragChanged();
if (d->drag)
@@ -337,6 +337,16 @@ void QQuickDropArea::dropEvent(QDropEvent *event)
The position of the drag event can be obtained from the \l x and \l y
properties, and the \l keys property identifies the drag keys of the event
\l source.
+
+ The existence of specific drag types can be determined using the \l hasColor,
+ \l hasHtml, \l hasText, and \l hasUrls properties.
+
+ The list of all supplied formats can be determined using the \l formats property.
+
+ Specific drag types can be obtained using the \l colorData, \l html, \l text,
+ and \l urls properties.
+
+ A string version of any available mimeType can be obtained using \l getDataAsString.
*/
/*!
@@ -357,14 +367,6 @@ void QQuickDropArea::dropEvent(QDropEvent *event)
This property holds the source of a drag event.
*/
-QObject *QQuickDropEvent::source()
-{
- if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData()))
- return dragMime->source();
- else
- return event->source();
-}
-
/*!
\qmlproperty stringlist QtQuick2::DragEvent::keys
@@ -372,11 +374,6 @@ QObject *QQuickDropEvent::source()
drag event.
*/
-QStringList QQuickDropEvent::keys() const
-{
- return d->getKeys(event->mimeData());
-}
-
/*!
\qmlproperty enumeration QtQuick2::DragEvent::action
@@ -400,6 +397,14 @@ QStringList QQuickDropEvent::keys() const
*/
/*!
+ \qmlproperty flags QtQuick2::DragEvent::proposedAction
+ \since QtQuick 2.2
+
+ This property holds the set of \l {action}{actions} proposed by the
+ drag source.
+*/
+
+/*!
\qmlproperty bool QtQuick2::DragEvent::accepted
This property holds whether the drag event was accepted by a handler.
@@ -416,6 +421,157 @@ QStringList QQuickDropEvent::keys() const
If an \a action is specified it will overwrite the value of the \l action property.
*/
+/*!
+ \qmlmethod QtQuick2::DragEvent::acceptProposedAction()
+ \since QtQuick 2.2
+
+ Accepts the drag event with the \l proposedAction.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::DragEvent::hasColor
+ \since QtQuick 2.2
+
+ This property holds whether the drag event contains a color item.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::DragEvent::hasHtml
+ \since QtQuick 2.2
+
+ This property holds whether the drag event contains a html item.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::DragEvent::hasText
+ \since QtQuick 2.2
+
+ This property holds whether the drag event contains a text item.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::DragEvent::hasUrls
+ \since QtQuick 2.2
+
+ This property holds whether the drag event contains one or more url items.
+*/
+
+/*!
+ \qmlproperty color QtQuick2::DragEvent::colorData
+ \since QtQuick 2.2
+
+ This property holds color data, if any.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::DragEvent::html
+ \since QtQuick 2.2
+
+ This property holds html data, if any.
+*/
+
+/*!
+ \qmlproperty string QtQuick2::DragEvent::text
+ \since QtQuick 2.2
+
+ This property holds text data, if any.
+*/
+
+/*!
+ \qmlproperty urllist QtQuick2::DragEvent::urls
+ \since QtQuick 2.2
+
+ This property holds a list of urls, if any.
+*/
+
+/*!
+ \qmlproperty stringlist QtQuick2::DragEvent::formats
+ \since QtQuick 2.2
+
+ This property holds a list of mime type formats contained in the drag data.
+*/
+
+/*!
+ \qmlmethod string QtQuick2::DragEvent::getDataAsString(string format)
+ \since QtQuick 2.2
+
+ Returns the data for the given \a format converted to a string. \a format should be one contained in the \l formats property.
+*/
+
+QObject *QQuickDropEvent::source()
+{
+ if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData()))
+ return dragMime->source();
+ else
+ return event->source();
+}
+
+QStringList QQuickDropEvent::keys() const
+{
+ return d->getKeys(event->mimeData());
+}
+
+bool QQuickDropEvent::hasColor() const
+{
+ return event->mimeData()->hasColor();
+}
+
+bool QQuickDropEvent::hasHtml() const
+{
+ return event->mimeData()->hasHtml();
+}
+
+bool QQuickDropEvent::hasText() const
+{
+ return event->mimeData()->hasText();
+}
+
+bool QQuickDropEvent::hasUrls() const
+{
+ return event->mimeData()->hasUrls();
+}
+
+QVariant QQuickDropEvent::colorData() const
+{
+ return event->mimeData()->colorData();
+}
+
+QString QQuickDropEvent::html() const
+{
+ return event->mimeData()->html();
+}
+
+QString QQuickDropEvent::text() const
+{
+ return event->mimeData()->text();
+}
+
+QList<QUrl> QQuickDropEvent::urls() const
+{
+ return event->mimeData()->urls();
+}
+
+QStringList QQuickDropEvent::formats() const
+{
+ return event->mimeData()->formats();
+}
+
+void QQuickDropEvent::getDataAsString(QQmlV4Function *args)
+{
+ if (args->length() != 0) {
+ QV4::Value v = (*args)[0];
+ QString format = v.toQString();
+ QString rv = QString::fromUtf8(event->mimeData()->data(format));
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine());
+ args->setReturnValue(QV4::Value::fromString(v4, rv));
+ }
+}
+
+void QQuickDropEvent::acceptProposedAction(QQmlV4Function *)
+{
+ event->acceptProposedAction();
+}
+
void QQuickDropEvent::accept(QQmlV4Function *args)
{
Qt::DropAction action = event->dropAction();
@@ -425,6 +581,7 @@ void QQuickDropEvent::accept(QQmlV4Function *args)
if (v.isInt32())
action = Qt::DropAction(v.integerValue());
}
+
// get action from arguments.
event->setDropAction(action);
event->accept();
diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h
index 3bdbe7f72e..6ba876ef34 100644
--- a/src/quick/items/qquickdroparea_p.h
+++ b/src/quick/items/qquickdroparea_p.h
@@ -62,8 +62,18 @@ class QQuickDropEvent : public QObject
Q_PROPERTY(QObject *source READ source)
Q_PROPERTY(QStringList keys READ keys)
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions)
+ Q_PROPERTY(Qt::DropActions proposedAction READ proposedAction)
Q_PROPERTY(Qt::DropAction action READ action WRITE setAction RESET resetAction)
Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
+ Q_PROPERTY(bool hasColor READ hasColor)
+ Q_PROPERTY(bool hasHtml READ hasHtml)
+ Q_PROPERTY(bool hasText READ hasText)
+ Q_PROPERTY(bool hasUrls READ hasUrls)
+ Q_PROPERTY(QVariant colorData READ colorData)
+ Q_PROPERTY(QString html READ html)
+ Q_PROPERTY(QString text READ text)
+ Q_PROPERTY(QList<QUrl> urls READ urls)
+ Q_PROPERTY(QStringList formats READ formats)
public:
QQuickDropEvent(QQuickDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {}
@@ -73,6 +83,7 @@ public:
QObject *source();
Qt::DropActions supportedActions() const { return event->possibleActions(); }
+ Qt::DropActions proposedAction() const { return event->proposedAction(); }
Qt::DropAction action() const { return event->dropAction(); }
void setAction(Qt::DropAction action) { event->setDropAction(action); }
void resetAction() { event->setDropAction(event->proposedAction()); }
@@ -82,6 +93,18 @@ public:
bool accepted() const { return event->isAccepted(); }
void setAccepted(bool accepted) { event->setAccepted(accepted); }
+ bool hasColor() const;
+ bool hasHtml() const;
+ bool hasText() const;
+ bool hasUrls() const;
+ QVariant colorData() const;
+ QString html() const;
+ QString text() const;
+ QList<QUrl> urls() const;
+ QStringList formats() const;
+
+ Q_INVOKABLE void getDataAsString(QQmlV4Function *);
+ Q_INVOKABLE void acceptProposedAction(QQmlV4Function *);
Q_INVOKABLE void accept(QQmlV4Function *);
private:
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index 6fe4b39974..be3011b204 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -571,14 +571,6 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
node = d->sceneGraphContext()->createImageNode();
}
- if (d->pixmapChanged) {
- // force update the texture in the node to trigger reconstruction of
- // geometry and the likes when a atlas segment has changed.
- node->setTexture(0);
- node->setTexture(texture);
- d->pixmapChanged = false;
- }
-
QRectF targetRect;
QRectF sourceRect;
QSGTexture::WrapMode hWrap = QSGTexture::ClampToEdge;
@@ -671,6 +663,17 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
sourceRect.width() / d->pix.width(),
sourceRect.height() / d->pix.height());
+ if (d->pixmapChanged) {
+ // force update the texture in the node to trigger reconstruction of
+ // geometry and the likes when a atlas segment has changed.
+ node->setTexture(0);
+ if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat))
+ node->setTexture(texture->removedFromAtlas());
+ else
+ node->setTexture(texture);
+ d->pixmapChanged = false;
+ }
+
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 1970a03bee..8a73a5d73d 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -61,137 +61,6 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
static const int PressAndHoldDelay = 800;
-#ifndef QT_NO_DRAGANDDROP
-
-QQuickDrag::QQuickDrag(QObject *parent)
-: QObject(parent), _target(0), _axis(XAndYAxis), _xmin(-FLT_MAX),
-_xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false)
-{
-}
-
-QQuickDrag::~QQuickDrag()
-{
-}
-
-QQuickItem *QQuickDrag::target() const
-{
- return _target;
-}
-
-void QQuickDrag::setTarget(QQuickItem *t)
-{
- if (_target == t)
- return;
- _target = t;
- emit targetChanged();
-}
-
-void QQuickDrag::resetTarget()
-{
- if (_target == 0)
- return;
- _target = 0;
- emit targetChanged();
-}
-
-QQuickDrag::Axis QQuickDrag::axis() const
-{
- return _axis;
-}
-
-void QQuickDrag::setAxis(QQuickDrag::Axis a)
-{
- if (_axis == a)
- return;
- _axis = a;
- emit axisChanged();
-}
-
-qreal QQuickDrag::xmin() const
-{
- return _xmin;
-}
-
-void QQuickDrag::setXmin(qreal m)
-{
- if (_xmin == m)
- return;
- _xmin = m;
- emit minimumXChanged();
-}
-
-qreal QQuickDrag::xmax() const
-{
- return _xmax;
-}
-
-void QQuickDrag::setXmax(qreal m)
-{
- if (_xmax == m)
- return;
- _xmax = m;
- emit maximumXChanged();
-}
-
-qreal QQuickDrag::ymin() const
-{
- return _ymin;
-}
-
-void QQuickDrag::setYmin(qreal m)
-{
- if (_ymin == m)
- return;
- _ymin = m;
- emit minimumYChanged();
-}
-
-qreal QQuickDrag::ymax() const
-{
- return _ymax;
-}
-
-void QQuickDrag::setYmax(qreal m)
-{
- if (_ymax == m)
- return;
- _ymax = m;
- emit maximumYChanged();
-}
-
-bool QQuickDrag::active() const
-{
- return _active;
-}
-
-void QQuickDrag::setActive(bool drag)
-{
- if (_active == drag)
- return;
- _active = drag;
- emit activeChanged();
-}
-
-bool QQuickDrag::filterChildren() const
-{
- return _filterChildren;
-}
-
-void QQuickDrag::setFilterChildren(bool filter)
-{
- if (_filterChildren == filter)
- return;
- _filterChildren = filter;
- emit filterChildrenChanged();
-}
-
-QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickDragAttached(obj);
-}
-
-#endif // QT_NO_DRAGANDDROP
-
QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
: enabled(true), hovered(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h
index fa32f32b65..ffe75ad843 100644
--- a/src/quick/items/qquickmousearea_p.h
+++ b/src/quick/items/qquickmousearea_p.h
@@ -49,78 +49,7 @@
QT_BEGIN_NAMESPACE
class QQuickMouseEvent;
-
-#ifndef QT_NO_DRAGANDDROP
-
-class QQuickDragAttached;
-class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
-{
- Q_OBJECT
-
- Q_ENUMS(Axis)
- Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
- Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
- Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
- Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
- Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
- Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
- Q_PROPERTY(bool active READ active NOTIFY activeChanged)
- Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
- //### consider drag and drop
-
-public:
- QQuickDrag(QObject *parent=0);
- ~QQuickDrag();
-
- QQuickItem *target() const;
- void setTarget(QQuickItem *target);
- void resetTarget();
-
- enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
- Axis axis() const;
- void setAxis(Axis);
-
- qreal xmin() const;
- void setXmin(qreal);
- qreal xmax() const;
- void setXmax(qreal);
- qreal ymin() const;
- void setYmin(qreal);
- qreal ymax() const;
- void setYmax(qreal);
-
- bool active() const;
- void setActive(bool);
-
- bool filterChildren() const;
- void setFilterChildren(bool);
-
- static QQuickDragAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void targetChanged();
- void axisChanged();
- void minimumXChanged();
- void maximumXChanged();
- void minimumYChanged();
- void maximumYChanged();
- void activeChanged();
- void filterChildrenChanged();
-
-private:
- QQuickItem *_target;
- Axis _axis;
- qreal _xmin;
- qreal _xmax;
- qreal _ymin;
- qreal _ymax;
- bool _active : 1;
- bool _filterChildren: 1;
- Q_DISABLE_COPY(QQuickDrag)
-};
-
-#endif // QT_NO_DRAGANDDROP
-
+class QQuickDrag;
class QQuickMouseAreaPrivate;
class QQuickWheelEvent;
// used in Qt Location
@@ -244,10 +173,6 @@ private:
QT_END_NAMESPACE
-#ifndef QT_NO_DRAGANDDROP
-QML_DECLARE_TYPE(QQuickDrag)
-QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
-#endif
QML_DECLARE_TYPE(QQuickMouseArea)
#endif // QQUICKMOUSEAREA_P_H
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index e91ab778c8..c195994de4 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -48,6 +48,7 @@
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmimedata.h>
#include <QtQml/qqmlinfo.h>
#include <QtGui/qevent.h>
#include <QTextBoundaryFinder>
@@ -2235,6 +2236,8 @@ void QQuickTextInput::setPasswordCharacter(const QString &str)
same value as the TextInput::text property. Otherwise,
this property holds the text visible to the user, while
the \l text property holds the actual entered text.
+
+ \readonly
*/
QString QQuickTextInput::displayText() const
{
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index aaadae5d1d..c8bc026868 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -46,6 +46,8 @@
#include "qquickitem_p.h"
#include "qquickevents_p_p.h"
+#include <private/qquickdrag_p.h>
+
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qsgflashnode_p.h>
@@ -279,6 +281,26 @@ void QQuickWindow::update()
d->windowManager->update(this);
}
+void forcePolishHelper(QQuickItem *item)
+{
+ if (item->flags() & QQuickItem::ItemHasContents) {
+ item->polish();
+ }
+
+ QList <QQuickItem *> items = item->childItems();
+ for (int i=0; i<items.size(); ++i)
+ forcePolishHelper(items.at(i));
+}
+
+/*!
+ Schedules polish events on all items in the scene.
+*/
+void QQuickWindow::forcePolish()
+{
+ Q_D(QQuickWindow);
+ forcePolishHelper(d->contentItem);
+}
+
void forceUpdate(QQuickItem *item)
{
if (item->flags() & QQuickItem::ItemHasContents)
@@ -344,6 +366,9 @@ QQuickWindowPrivate::QQuickWindowPrivate()
#ifndef QT_NO_CURSOR
, cursorItem(0)
#endif
+#ifndef QT_NO_DRAGANDDROP
+ , dragGrabber(0)
+#endif
, touchMouseId(-1)
, touchMousePressTimestamp(0)
, dirtyItemList(0)
@@ -360,6 +385,9 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, renderTargetId(0)
, incubationController(0)
{
+#ifndef QT_NO_DRAGANDDROP
+ dragGrabber = new QQuickDragGrabber;
+#endif
}
QQuickWindowPrivate::~QQuickWindowPrivate()
@@ -389,6 +417,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection);
QObject::connect(q, SIGNAL(focusObjectChanged(QObject*)), q, SIGNAL(activeFocusItemChanged()));
+ QObject::connect(q, SIGNAL(screenChanged(QScreen*)), q, SLOT(forcePolish()));
}
/*!
@@ -963,7 +992,9 @@ QQuickWindow::~QQuickWindow()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete d->incubationController; d->incubationController = 0;
-
+#ifndef QT_NO_DRAGANDDROP
+ delete d->dragGrabber; d->dragGrabber = 0;
+#endif
delete d->contentItem; d->contentItem = 0;
}
@@ -1181,7 +1212,7 @@ bool QQuickWindow::event(QEvent *e)
case QEvent::DragLeave:
case QEvent::DragMove:
case QEvent::Drop:
- d->deliverDragEvent(&d->dragGrabber, e);
+ d->deliverDragEvent(d->dragGrabber, e);
break;
#endif
case QEvent::WindowDeactivate:
@@ -3053,6 +3084,68 @@ void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
}
/*!
+ \since 5.2
+
+ Call this function to reset the OpenGL context its default state.
+
+ The scene graph uses the OpenGL context and will both rely on and
+ clobber its state. When mixing raw OpenGL commands with scene
+ graph rendering, this function provides a convenient way of
+ resetting the OpenGL context state back to its default values.
+
+ This function does not touch state in the fixed-function pipeline.
+
+ This function does not clear the color, depth and stencil buffers. Use
+ QQuickWindow::setClearBeforeRendering to control clearing of the color
+ buffer. The depth and stencil buffer might be clobbered by the scene
+ graph renderer. Clear these manually on demand.
+
+ \sa QQuickWindow::beforeRendering()
+ */
+void QQuickWindow::resetOpenGLState()
+{
+ if (!openglContext())
+ return;
+
+ QOpenGLFunctions *gl = openglContext()->functions();
+
+ gl->glBindBuffer(GL_ARRAY_BUFFER, 0);
+ gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ int maxAttribs;
+ glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
+ for (int i=0; i<maxAttribs; ++i) {
+ gl->glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
+ gl->glDisableVertexAttribArray(i);
+ }
+
+ gl->glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_SCISSOR_TEST);
+
+ glColorMask(true, true, true, true);
+ glClearColor(0, 0, 0, 0);
+
+ glDepthMask(true);
+ glDepthFunc(GL_LESS);
+ gl->glClearDepthf(1);
+
+ glStencilMask(0xff);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_ALWAYS, 0, 0xff);
+
+ glDisable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ZERO);
+
+ gl->glUseProgram(0);
+
+ QOpenGLFramebufferObject::bindDefault();
+}
+
+/*!
\qmlproperty string QtQuick.Window2::Window::title
The window's title in the windowing system.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index fad67e9734..a1ef9e1593 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -100,6 +100,8 @@ public:
uint renderTargetId() const;
QSize renderTargetSize() const;
+ void resetOpenGLState();
+
QQmlIncubationController *incubationController() const;
#ifndef QT_NO_ACCESSIBILITY
@@ -141,6 +143,7 @@ Q_SIGNALS:
public Q_SLOTS:
void update();
+ void forcePolish();
void releaseResources();
protected:
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index aa7d7c5128..ad861754d7 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -57,7 +57,6 @@
#include "qquickwindow.h"
#include <QtQuick/private/qsgcontext_p.h>
-#include <private/qquickdrag_p.h>
#include <QtCore/qthread.h>
#include <QtCore/qmutex.h>
@@ -73,6 +72,7 @@ QT_BEGIN_NAMESPACE
//Make it easy to identify and customize the root item if needed
class QSGRenderLoop;
+class QQuickDragGrabber;
class QQuickRootItem : public QQuickItem
{
@@ -116,7 +116,7 @@ public:
QQuickItem *cursorItem;
#endif
#ifndef QT_NO_DRAGANDDROP
- QQuickDragGrabber dragGrabber;
+ QQuickDragGrabber *dragGrabber;
#endif
int touchMouseId;
bool checkIfDoubleClicked(ulong newPressEventTimestamp);
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 8d4b4dd9f6..cf71489f88 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -46,6 +46,10 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLFramebufferObject>
+#ifndef GL_DOUBLE
+ #define GL_DOUBLE 0x140A
+#endif
+
QT_BEGIN_NAMESPACE
extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input);
@@ -191,7 +195,7 @@ void qsg_dumpShadowRoots(BatchRootInfo *i, int indent)
if (!i) {
qDebug() << ind.constData() << "- no info";
} else {
- qDebug() << ind.constData() << "- parent:" << i->parentRoot;
+ qDebug() << ind.constData() << "- parent:" << i->parentRoot << "orders" << i->firstOrder << "->" << i->lastOrder << ", avail:" << i->availableOrders;
for (QSet<Node *>::const_iterator it = i->subRoots.constBegin();
it != i->subRoots.constEnd(); ++it) {
qDebug() << ind.constData() << "-" << *it;
@@ -213,7 +217,10 @@ void qsg_dumpShadowRoots(Node *n)
qDebug() << ind.constData() << "[X]" << n->sgNode << hex << uint(n->sgNode->flags());
qsg_dumpShadowRoots(n->rootInfo(), indent);
} else {
- qDebug() << ind.constData() << "[ ]" << n->sgNode << hex << uint(n->sgNode->flags());
+ QDebug d = qDebug();
+ d << ind.constData() << "[ ]" << n->sgNode << hex << uint(n->sgNode->flags());
+ if (n->type() == QSGNode::GeometryNodeType)
+ d << "order" << dec << n->element()->order;
}
SHADOWNODE_TRAVERSE(n)
@@ -619,7 +626,8 @@ Renderer::Renderer(QSGContext *ctx)
, m_opaqueRenderList(64)
, m_alphaRenderList(64)
, m_nextRenderOrder(0)
- , m_explicitOrdering(false)
+ , m_partialRebuild(false)
+ , m_partialRebuildRoot(0)
, m_opaqueBatches(16)
, m_alphaBatches(16)
, m_batchPool(16)
@@ -818,14 +826,16 @@ void Renderer::nodeWasTransformed(Node *node, int *vertexCount)
e->boundsComputed = false;
if (e->batch) {
if (!e->batch->isOpaque) {
- e->batch->invalidate();
- m_rebuild |= BuildBatches;
+ if (e->root) {
+ m_taggedRoots << e->root;
+ m_rebuild |= BuildRenderListsForTaggedRoots;
+ } else {
+ m_rebuild |= FullRebuild;
+ }
} else if (e->batch->merged) {
e->batch->needsUpload = true;
}
}
- if (e->batch && e->batch->merged)
- e->batch->needsUpload = true;
}
}
@@ -1022,7 +1032,12 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
if (!e->batch->geometryWasChanged(gn)) {
m_rebuild |= Renderer::FullRebuild;
} else if (!b->isOpaque) {
- m_rebuild |= Renderer::BuildBatches;
+ if (e->root) {
+ m_taggedRoots << e->root;
+ m_rebuild |= BuildRenderListsForTaggedRoots;
+ } else {
+ m_rebuild |= FullRebuild;
+ }
} else {
b->needsUpload = true;
}
@@ -1030,8 +1045,7 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
}
}
- if (state & QSGNode::DirtyMaterial) {
- Q_ASSERT(node->type() == QSGNode::GeometryNodeType);
+ if (state & QSGNode::DirtyMaterial && node->type() == QSGNode::GeometryNodeType) {
Element *e = shadowNode->element();
if (e) {
if (e->batch) {
@@ -1104,30 +1118,27 @@ void Renderer::buildRenderLists(QSGNode *node)
m_alphaRenderList << e;
e->order = ++m_nextRenderOrder;
-
// Used while rebuilding partial roots.
- if (m_explicitOrdering)
+ if (m_partialRebuild)
e->orphaned = false;
} else if (node->type() == QSGNode::ClipNodeType || shadowNode->isBatchRoot) {
Q_ASSERT(m_nodes.contains(node));
BatchRootInfo *info = batchRootInfo(m_nodes.value(node));
- Q_ASSERT(!m_explicitOrdering || info->firstOrder >= 0);
- Q_ASSERT(!m_explicitOrdering || info->lastOrder >= 0);
-
- if (m_explicitOrdering)
+ if (node == m_partialRebuildRoot) {
m_nextRenderOrder = info->firstOrder;
- int currentOrder = m_nextRenderOrder;
- QSGNODE_TRAVERSE(node)
- buildRenderLists(child);
- int padding = (m_nextRenderOrder - currentOrder) >> 2;
- if (m_explicitOrdering) {
+ QSGNODE_TRAVERSE(node)
+ buildRenderLists(child);
m_nextRenderOrder = info->lastOrder + 1;
} else {
+ int currentOrder = m_nextRenderOrder;
+ QSGNODE_TRAVERSE(node)
+ buildRenderLists(child);
+ int padding = (m_nextRenderOrder - currentOrder) >> 2;
info->firstOrder = currentOrder;
info->availableOrders = padding;
info->lastOrder = m_nextRenderOrder + padding;
- m_nextRenderOrder += padding;
+ m_nextRenderOrder = info->lastOrder;
}
return;
} else if (node->type() == QSGNode::RenderNodeType) {
@@ -1222,7 +1233,7 @@ void Renderer::buildRenderListsForTaggedRoots()
m_opaqueRenderList.reset();
m_alphaRenderList.reset();
int maxRenderOrder = m_nextRenderOrder;
- m_explicitOrdering = true;
+ m_partialRebuild = true;
// Traverse each root, assigning it
for (QSet<Node *>::const_iterator it = m_taggedRoots.constBegin();
it != m_taggedRoots.constEnd(); ++it) {
@@ -1231,11 +1242,13 @@ void Renderer::buildRenderListsForTaggedRoots()
if ((!i->parentRoot || !m_taggedRoots.contains(i->parentRoot))
&& !nodeUpdater()->isNodeBlocked(root->sgNode, rootNode())) {
m_nextRenderOrder = i->firstOrder;
+ m_partialRebuildRoot = root->sgNode;
buildRenderLists(root->sgNode);
}
}
+ m_partialRebuild = false;
+ m_partialRebuildRoot = 0;
m_taggedRoots.clear();
- m_explicitOrdering = false;
m_nextRenderOrder = qMax(m_nextRenderOrder, maxRenderOrder);
// Add orphaned elements back into the list and then sort it..
@@ -1783,6 +1796,7 @@ void Renderer::renderMergedBatch(const Batch *batch)
if (Q_UNLIKELY(debug_render)) {
QDebug debug = qDebug();
debug << " -"
+ << batch
<< (batch->uploadedThisFrame ? "[ upload]" : "[retained]")
<< (e->node->clipList() ? "[ clip]" : "[noclip]")
<< (batch->isOpaque ? "[opaque]" : "[ alpha]")
@@ -1860,6 +1874,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
if (Q_UNLIKELY(debug_render)) {
qDebug() << " -"
+ << batch
<< (batch->uploadedThisFrame ? "[ upload]" : "[retained]")
<< (e->node->clipList() ? "[ clip]" : "[noclip]")
<< (batch->isOpaque ? "[opaque]" : "[ alpha]")
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 6f7694deac..1aa165281a 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -450,7 +450,8 @@ private:
QDataBuffer<Element *> m_opaqueRenderList;
QDataBuffer<Element *> m_alphaRenderList;
int m_nextRenderOrder;
- bool m_explicitOrdering;
+ bool m_partialRebuild;
+ QSGNode *m_partialRebuildRoot;
QHash<QSGRenderNode *, RenderNodeElement *> m_renderNodeElements;
QDataBuffer<Batch *> m_opaqueBatches;
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index 7f09af4da3..ffb11fc6fa 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -406,6 +406,7 @@ QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
, m_vertex_usage_pattern(AlwaysUploadPattern)
, m_line_width(1.0)
{
+ Q_UNUSED(m_reserved_bits);
Q_ASSERT(m_attributes.count > 0);
Q_ASSERT(m_attributes.stride > 0);
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 713469f94a..fab3287087 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -166,6 +166,7 @@ static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
*/
QSGMaterialShader::QSGMaterialShader()
{
+ Q_UNUSED(m_reserved);
}
/*!
@@ -544,6 +545,7 @@ static void qt_print_material_count()
QSGMaterial::QSGMaterial()
: m_flags(0)
{
+ Q_UNUSED(m_reserved);
#ifndef QT_NO_DEBUG
if (qsg_leak_check) {
++qt_material_count;
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index a55a5abb0a..9d3d08e057 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -1053,6 +1053,7 @@ void QSGGeometryNode::setInheritedOpacity(qreal opacity)
QSGClipNode::QSGClipNode()
: QSGBasicGeometryNode(ClipNodeType)
{
+ Q_UNUSED(m_reserved);
}
diff --git a/src/quick/scenegraph/util/qsgsimplerectnode.cpp b/src/quick/scenegraph/util/qsgsimplerectnode.cpp
index 1e77ef5b0c..55e5ee9e3b 100644
--- a/src/quick/scenegraph/util/qsgsimplerectnode.cpp
+++ b/src/quick/scenegraph/util/qsgsimplerectnode.cpp
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
QSGSimpleRectNode::QSGSimpleRectNode(const QRectF &rect, const QColor &color)
: m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
{
+ Q_UNUSED(reserved);
QSGGeometry::updateRectGeometry(&m_geometry, rect);
m_material.setColor(color);
setMaterial(&m_material);
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 6a6bcbf7f8..c7bc8a4076 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -493,6 +493,8 @@ QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
void QSGTexture::updateBindOptions(bool force)
{
Q_D(QSGTexture);
+ force |= isAtlasTexture();
+
if (force || d->filteringChanged) {
bool linear = d->filterMode == Linear;
GLint minFilter = linear ? GL_LINEAR : GL_NEAREST;
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index e0c20307a8..4f21231184 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -72,6 +72,7 @@ private slots:
void qtbug_22535();
void evalAfterInvalidate();
+ void qobjectDerived();
private:
QQmlEngine engine;
@@ -659,6 +660,26 @@ void tst_qqmlcontext::evalAfterInvalidate()
QCoreApplication::processEvents();
}
+void tst_qqmlcontext::qobjectDerived()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("refreshExpressions.qml"));
+
+ CountCommand command;
+ // This test is similar to refreshExpressions, but with the key difference that
+ // we use the QVariant overload of setContextProperty. That way, we test that
+ // QVariant knowledge that it contains a QObject derived pointer is used.
+ engine.rootContext()->setContextProperty("countCommand", QVariant::fromValue(&command));
+
+ // We use a fresh context here to bypass any root-context optimizations in
+ // the engine
+ QQmlContext context(engine.rootContext());
+
+ QObject *o1 = component.create(&context);
+
+ QCOMPARE(command.count, 2);
+}
+
QTEST_MAIN(tst_qqmlcontext)
#include "tst_qqmlcontext.moc"
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 1db3bc3fe8..99659fb1eb 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -55,6 +55,7 @@
#include "../../shared/util.h"
#include <private/qv4functionobject_p.h>
#include <private/qv4exception_p.h>
+#include <private/qv4scopedvalue_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -2260,9 +2261,9 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::Value &o, const
QV4::FunctionObject *function = program.run().asFunctionObject();
if (!function)
return false;
- CALLDATA(1);
- d.args[0] = o;
- d.thisObject = engine->global();
+ QV4::ScopedCallData d(ctx->engine, 1);
+ d->args[0] = o;
+ d->thisObject = engine->global();
function->call(d);
} catch (QV4::Exception &e) {
e.accept(ctx);
@@ -2285,11 +2286,14 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::Value &o,
QV4::FunctionObject *function = program.run().asFunctionObject();
if (!function)
return false;
- CALLDATA(1);
- d.args[0] = o;
- d.thisObject = engine->global();
- QV4::Value value = function->call(d);
- return __qmljs_strict_equal(value, result);
+ QV4::ValueScope scope(ctx);
+ QV4::ScopedValue value(scope);
+ QV4::ScopedValue res(scope, result);
+ QV4::ScopedCallData d(ctx->engine, 1);
+ d->args[0] = o;
+ d->thisObject = engine->global();
+ value = function->call(d);
+ return __qmljs_strict_equal(value, res);
} catch (QV4::Exception &e) {
e.accept(ctx);
}
@@ -2309,9 +2313,9 @@ static inline QV4::Value evaluate(QV8Engine *engine, const QV4::Value & o,
QV4::FunctionObject *function = program.run().asFunctionObject();
if (!function)
return QV4::Value::emptyValue();
- CALLDATA(1);
- d.args[0] = o;
- d.thisObject = engine->global();
+ QV4::ScopedCallData d(ctx->engine, 1);
+ d->args[0] = o;
+ d->thisObject = engine->global();
QV4::Value value = function->call(d);
return value;
} catch (QV4::Exception &e) {
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index b5c8edf5f3..acb623989a 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -198,6 +198,18 @@ private:
QStringList defaultImportPathList;
void testType(const QString& qml, const QString& type, const QString& error, bool partialMatch = false);
+
+ // When calling into JavaScript, the specific type of the return value can differ if that return
+ // value is a number. This is not only the case for non-integral numbers, or numbers that do not
+ // fit into the (signed) integer range, but it also depends on which optimizations are run. So,
+ // to check if the return value is of a number type, use this method instead of checking against
+ // a specific userType.
+ static bool isJSNumberType(int userType)
+ {
+ return userType == (int) QVariant::Int
+ || userType == (int) QVariant::UInt
+ || userType == (int) QVariant::Double;
+ }
};
#define DETERMINE_ERRORS(errorfile,expected,actual)\
@@ -841,8 +853,8 @@ void tst_qqmllanguage::bindJSValueToVar()
QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
- QCOMPARE(object->property("test1Bound").userType(), (int)QVariant::Int);
- QCOMPARE(object->property("test20Bound").userType(), (int)QVariant::Double);
+ QVERIFY(isJSNumberType(object->property("test1Bound").userType()));
+ QVERIFY(isJSNumberType(object->property("test20Bound").userType()));
QCOMPARE(object->property("test1"), QVariant(5));
QCOMPARE(object->property("test2"), QVariant((double)1.7));
@@ -890,8 +902,8 @@ void tst_qqmllanguage::bindJSValueToVariant()
QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
- QCOMPARE(object->property("test1Bound").userType(), (int)QVariant::Int);
- QCOMPARE(object->property("test20Bound").userType(), (int)QVariant::Double);
+ QVERIFY(isJSNumberType(object->property("test1Bound").userType()));
+ QVERIFY(isJSNumberType(object->property("test20Bound").userType()));
QCOMPARE(object->property("test1"), QVariant(5));
QCOMPARE(object->property("test2"), QVariant((double)1.7));
@@ -3004,7 +3016,6 @@ void tst_qqmllanguage::signalParameterTypes()
QQmlComponent component(&engine, testFileUrl("signalParameterTypes.2.qml"));
QObject *obj = component.create();
QVERIFY(obj != 0);
- QEXPECT_FAIL("", "Dynamic connections don't enforce type safety - QTBUG-26662", Abort);
QVERIFY(obj->property("success").toBool());
delete obj;
}
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index 5d6d0d66de..b1f83fcd6c 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -246,7 +246,7 @@ void tst_QQmlMetaObject::property()
QCOMPARE(signal.methodType(), QMetaMethod::Signal);
QCOMPARE(signal.name(), QByteArray("testChanged"));
QCOMPARE(signal.methodSignature(), QByteArray("testChanged()"));
- QCOMPARE(signal.access(), QMetaMethod::Protected);
+ QCOMPARE(signal.access(), QMetaMethod::Public);
QCOMPARE(signal.parameterCount(), 0);
QCOMPARE(signal.parameterTypes(), QList<QByteArray>());
QCOMPARE(signal.parameterNames(), QList<QByteArray>());
@@ -379,7 +379,7 @@ void tst_QQmlMetaObject::method()
QMetaMethod method = mo->method(mo->methodOffset());
QCOMPARE(method.methodType(), methodType);
QCOMPARE(QString::fromUtf8(method.methodSignature().constData()), signature);
- QCOMPARE(method.access(), QMetaMethod::Protected);
+ QCOMPARE(method.access(), QMetaMethod::Public);
QString computedName = signature.left(signature.indexOf('('));
QCOMPARE(QString::fromUtf8(method.name()), computedName);
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 418e2edf27..27c3fd985e 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -57,11 +57,24 @@ class MyQmlObject : public QObject
{
Q_OBJECT
public:
- MyQmlObject() {}
+ MyQmlObject(QObject *parent = 0) : QObject(parent) {}
};
QML_DECLARE_TYPE(MyQmlObject);
+class MyQObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyQObject(QObject *parent = 0) : QObject(parent), m_i(0) {}
+
+ int inc() { return ++m_i; }
+
+private:
+ int m_i;
+};
+
+
class MyAttached : public QObject
{
Q_OBJECT
@@ -316,10 +329,11 @@ class PropertyObject : public QObject
Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject)
+ Q_PROPERTY(MyQObject *qObject READ qObject WRITE setQObject NOTIFY qObjectChanged)
Q_CLASSINFO("DefaultProperty", "defaultProperty")
public:
- PropertyObject() : m_resetProperty(9) {}
+ PropertyObject() : m_resetProperty(9), m_qObject(0) {}
int defaultProperty() { return 10; }
QRect rectProperty() { return QRect(10, 10, 1, 209); }
@@ -342,9 +356,19 @@ public:
MyQmlObject *qmlObject() { return &m_qmlObject; }
+ MyQObject *qObject() { return m_qObject; }
+ void setQObject(MyQObject *object)
+ {
+ if (m_qObject != object) {
+ m_qObject = object;
+ emit qObjectChanged();
+ }
+ }
+
signals:
void clicked();
void oddlyNamedNotifySignal();
+ void qObjectChanged();
private:
int m_resetProperty;
@@ -353,6 +377,7 @@ private:
QVariantMap m_variantMap;
int m_propertyWithNotify;
MyQmlObject m_qmlObject;
+ MyQObject *m_qObject;
};
QML_DECLARE_TYPE(PropertyObject);
@@ -1130,6 +1155,18 @@ void tst_qqmlproperty::read()
QCOMPARE(p.read(), QVariant());
}
+ // Object property registered with Qt, but not registered with QML.
+ {
+ PropertyObject o;
+ QQmlProperty p(&o, "qObject");
+ QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
+
+ QCOMPARE(p.propertyType(), qMetaTypeId<MyQObject*>());
+ QVariant v = p.read();
+ QVERIFY(v.canConvert(QMetaType::QObjectStar));
+ QVERIFY(qvariant_cast<QObject *>(v) == o.qObject());
+ }
+
// Object property
{
PropertyObject o;
@@ -1387,6 +1424,23 @@ void tst_qqmlproperty::write()
QCOMPARE(p.read(), QVariant(99));
delete object;
}
+ // Writable pointer to QObject derived
+ {
+ PropertyObject o;
+ QQmlProperty p(&o, QString("qObject"));
+ QCOMPARE(o.qObject(), (QObject*)0);
+ QObject *newObject = new MyQObject(this);
+ QCOMPARE(p.write(QVariant::fromValue(newObject)), true);
+ QCOMPARE(o.qObject(), newObject);
+ QVariant data = p.read();
+ QCOMPARE(data.value<QObject*>(), newObject);
+ QCOMPARE(data.value<MyQObject*>(), newObject);
+ // Incompatible types can not be written.
+ QCOMPARE(p.write(QVariant::fromValue(new MyQmlObject(this))), false);
+ QVariant newData = p.read();
+ QCOMPARE(newData.value<QObject*>(), newObject);
+ QCOMPARE(newData.value<MyQObject*>(), newObject);
+ }
}
void tst_qqmlproperty::reset()
diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
index 7d8f02a952..9da67c3f43 100644
--- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
@@ -192,7 +192,7 @@ void tst_qv4debugger::breakAnywhere()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->pause(m_v4->debugger);
+ m_debuggerAgent->pauseAll();
evaluateJavaScript(script, "testFile");
QVERIFY(m_debuggerAgent->m_wasPaused);
}
@@ -203,7 +203,7 @@ void tst_qv4debugger::pendingBreakpoint()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->addBreakPoint(m_v4->debugger, "testfile", 2);
+ m_debuggerAgent->addBreakPoint("testfile", 2);
evaluateJavaScript(script, "testfile");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 1);
@@ -219,7 +219,7 @@ void tst_qv4debugger::liveBreakPoint()
"var j = i + 1\n"
"var k = i\n";
m_debuggerAgent->m_breakPointsToAddWhenPaused << TestAgent::TestBreakPoint("liveBreakPoint", 3);
- m_debuggerAgent->pause(m_v4->debugger);
+ m_debuggerAgent->pauseAll();
evaluateJavaScript(script, "liveBreakPoint");
QVERIFY(m_debuggerAgent->m_wasPaused);
QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 2);
@@ -234,8 +234,8 @@ void tst_qv4debugger::removePendingBreakPoint()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->addBreakPoint(m_v4->debugger, "removePendingBreakPoint", 2);
- m_debuggerAgent->removeBreakPoint(m_v4->debugger, "removePendingBreakPoint", 2);
+ m_debuggerAgent->addBreakPoint("removePendingBreakPoint", 2);
+ m_debuggerAgent->removeBreakPoint("removePendingBreakPoint", 2);
evaluateJavaScript(script, "removePendingBreakPoint");
QVERIFY(!m_debuggerAgent->m_wasPaused);
}
@@ -246,7 +246,7 @@ void tst_qv4debugger::addBreakPointWhilePaused()
"var i = 42;\n"
"var j = i + 1\n"
"var k = i\n";
- m_debuggerAgent->addBreakPoint(m_v4->debugger, "addBreakPointWhilePaused", 1);
+ m_debuggerAgent->addBreakPoint("addBreakPointWhilePaused", 1);
m_debuggerAgent->m_breakPointsToAddWhenPaused << TestAgent::TestBreakPoint("addBreakPointWhilePaused", 2);
evaluateJavaScript(script, "addBreakPointWhilePaused");
QVERIFY(m_debuggerAgent->m_wasPaused);
@@ -276,7 +276,7 @@ void tst_qv4debugger::removeBreakPointForNextInstruction()
QMetaObject::invokeMethod(m_engine, "injectFunction", Qt::BlockingQueuedConnection,
Q_ARG(QString, "someCall"), Q_ARG(TestEngine::InjectedFunction, someCall));
- m_debuggerAgent->addBreakPoint(m_v4->debugger, "removeBreakPointForNextInstruction", 2);
+ m_debuggerAgent->addBreakPoint("removeBreakPointForNextInstruction", 2);
evaluateJavaScript(script, "removeBreakPointForNextInstruction");
QVERIFY(!m_debuggerAgent->m_wasPaused);
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 5e7370f8a5..de1c12097b 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -41,6 +41,7 @@
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
+#include <QtQuick/private/qquickdrag_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <private/qquickflickable_p.h>
diff --git a/tools/v4/main.cpp b/tools/v4/main.cpp
index e4a03339e1..a49c7093cf 100644
--- a/tools/v4/main.cpp
+++ b/tools/v4/main.cpp
@@ -77,10 +77,10 @@ struct Print: FunctionObject
name = scope->engine->newString("print");
}
- static Value call(Managed *, const CallData &d)
+ static Value call(Managed *, CallData *callData)
{
- for (int i = 0; i < d.argc; ++i) {
- QString s = d.args[i].toQString();
+ for (int i = 0; i < callData->argc; ++i) {
+ QString s = callData->args[i].toQString();
if (i)
std::cout << ' ';
std::cout << qPrintable(s);
@@ -102,7 +102,7 @@ struct GC: public FunctionObject
vtbl = &static_vtbl;
name = scope->engine->newString("gc");
}
- static Value call(Managed *m, const CallData &)
+ static Value call(Managed *m, CallData *)
{
m->engine()->memoryManager->runGC();
return Value::undefinedValue();