aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/jsruntime.pri10
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp58
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4calldata_p.h113
-rw-r--r--src/qml/jsruntime/qv4context.cpp14
-rw-r--r--src/qml/jsruntime/qv4context_p.h5
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp465
-rw-r--r--src/qml/jsruntime/qv4engine_p.h150
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h17
-rw-r--r--src/qml/jsruntime/qv4function.cpp36
-rw-r--r--src/qml/jsruntime/qv4function_p.h25
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4global_p.h60
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp16
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp21
-rw-r--r--src/qml/jsruntime/qv4include.cpp29
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp13
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp12
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h17
-rw-r--r--src/qml/jsruntime/qv4managed_p.h1
-rw-r--r--src/qml/jsruntime/qv4mapobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4math_p.h27
-rw-r--r--src/qml/jsruntime/qv4object.cpp29
-rw-r--r--src/qml/jsruntime/qv4object_p.h20
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h2
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp26
-rw-r--r--src/qml/jsruntime/qv4propertykey_p.h6
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp11
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp48
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp2
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp43
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp453
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h4
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h586
-rw-r--r--src/qml/jsruntime/qv4runtimecodegen.cpp1
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp427
-rw-r--r--src/qml/jsruntime/qv4setobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4stackframe_p.h50
-rw-r--r--src/qml/jsruntime/qv4string.cpp5
-rw-r--r--src/qml/jsruntime/qv4string_p.h36
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4stringtoarrayindex_p.h (renamed from src/qml/jsruntime/qv4serialize_p.h)48
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp42
-rw-r--r--src/qml/jsruntime/qv4value.cpp6
-rw-r--r--src/qml/jsruntime/qv4value_p.h18
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp316
-rw-r--r--src/qml/jsruntime/qv4vtable_p.h6
52 files changed, 1641 insertions, 1706 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index a24ee0a188..e6f1079aa7 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -3,6 +3,7 @@ INCLUDEPATH += $$OUT_PWD
!qmldevtools_build {
SOURCES += \
+ $$PWD/qv4engine.cpp \
$$PWD/qv4context.cpp \
$$PWD/qv4persistent.cpp \
$$PWD/qv4lookup.cpp \
@@ -36,13 +37,13 @@ SOURCES += \
$$PWD/qv4reflect.cpp \
$$PWD/qv4regexpobject.cpp \
$$PWD/qv4stackframe.cpp \
+ $$PWD/qv4string.cpp \
$$PWD/qv4stringiterator.cpp \
$$PWD/qv4stringobject.cpp \
$$PWD/qv4variantobject.cpp \
$$PWD/qv4objectiterator.cpp \
$$PWD/qv4regexp.cpp \
$$PWD/qv4runtimecodegen.cpp \
- $$PWD/qv4serialize.cpp \
$$PWD/qv4script.cpp \
$$PWD/qv4symbol.cpp \
$$PWD/qv4setobject.cpp \
@@ -103,13 +104,13 @@ HEADERS += \
$$PWD/qv4regexpobject_p.h \
$$PWD/qv4runtimecodegen_p.h \
$$PWD/qv4stackframe_p.h \
+ $$PWD/qv4string_p.h \
$$PWD/qv4stringiterator_p.h \
$$PWD/qv4stringobject_p.h \
$$PWD/qv4variantobject_p.h \
$$PWD/qv4property_p.h \
$$PWD/qv4objectiterator_p.h \
$$PWD/qv4regexp_p.h \
- $$PWD/qv4serialize_p.h \
$$PWD/qv4script_p.h \
$$PWD/qv4symbol_p.h \
$$PWD/qv4setobject_p.h \
@@ -142,18 +143,17 @@ qtConfig(qml-sequence-object) {
HEADERS += \
+ $$PWD/qv4calldata_p.h \
$$PWD/qv4runtime_p.h \
$$PWD/qv4runtimeapi_p.h \
$$PWD/qv4value_p.h \
- $$PWD/qv4string_p.h \
+ $$PWD/qv4stringtoarrayindex_p.h \
$$PWD/qv4util_p.h \
$$PWD/qv4value_p.h \
$$PWD/qv4functiontable_p.h
SOURCES += \
- $$PWD/qv4engine.cpp \
$$PWD/qv4runtime.cpp \
- $$PWD/qv4string.cpp \
$$PWD/qv4value.cpp \
$$PWD/qv4executableallocator.cpp
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 4a21f62cf2..98e0ef9e70 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -116,6 +116,9 @@ bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
args->fullyCreate();
+ if (!id.isArrayIndex())
+ return Object::virtualDefineOwnProperty(m, id, desc, attrs);
+
uint index = id.asArrayIndex();
if (!args->isMapped(index))
@@ -148,36 +151,42 @@ bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const
ReturnedValue ArgumentsObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
- const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- uint index = id.asArrayIndex();
- if (index < args->d()->argCount && !args->d()->fullyCreated) {
- if (hasProperty)
- *hasProperty = true;
- return args->context()->args()[index].asReturnedValue();
+ if (id.isArrayIndex()) {
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
+ uint index = id.asArrayIndex();
+ if (index < args->d()->argCount && !args->d()->fullyCreated) {
+ if (hasProperty)
+ *hasProperty = true;
+ return args->context()->args()[index].asReturnedValue();
+ }
+
+ if (args->isMapped(index)) {
+ Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
+ if (hasProperty)
+ *hasProperty = true;
+ return args->context()->args()[index].asReturnedValue();
+ }
}
- if (!args->isMapped(index))
- return Object::virtualGet(m, id, receiver, hasProperty);
- Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
- if (hasProperty)
- *hasProperty = true;
- return args->context()->args()[index].asReturnedValue();
+ return Object::virtualGet(m, id, receiver, hasProperty);
}
bool ArgumentsObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- uint index = id.asArrayIndex();
-
- if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
- args->context()->setArg(index, value);
- return true;
+ if (id.isArrayIndex()) {
+ ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ uint index = id.asArrayIndex();
+
+ if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
+ args->context()->setArg(index, value);
+ return true;
+ }
+
+ bool isMapped = (args == receiver && args->isMapped(index));
+ if (isMapped)
+ args->context()->setArg(index, value);
}
- bool isMapped = (args == receiver && args->isMapped(index));
- if (isMapped)
- args->context()->setArg(index, value);
-
return Object::virtualPut(m, id, value, receiver);
}
@@ -186,13 +195,16 @@ bool ArgumentsObject::virtualDeleteProperty(Managed *m, PropertyKey id)
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
args->fullyCreate();
bool result = Object::virtualDeleteProperty(m, id);
- if (result)
+ if (result && id.isArrayIndex())
args->removeMapping(id.asArrayIndex());
return result;
}
PropertyAttributes ArgumentsObject::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
{
+ if (!id.isArrayIndex())
+ return Object::virtualGetOwnProperty(m, id, p);
+
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
uint index = id.asArrayIndex();
if (index < args->d()->argCount && !args->d()->fullyCreated) {
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index b5b421fa39..b3e607d74a 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -219,7 +219,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
// Item iteration supported, so let's go ahead and try use that.
ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, false, 0));
CHECK_EXCEPTION();
- ScopedObject iterator(scope, Runtime::method_getIterator(scope.engine, itemsObject, true));
+ ScopedObject iterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject, true));
CHECK_EXCEPTION(); // symbol_iterator threw; whoops.
if (!iterator) {
return scope.engine->throwTypeError(); // symbol_iterator wasn't an object.
@@ -236,11 +236,11 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
if (k > (static_cast<qint64>(1) << 53) - 1) {
ScopedValue falsey(scope, Encode(false));
ScopedValue error(scope, scope.engine->throwTypeError());
- return Runtime::method_iteratorClose(scope.engine, iterator, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iterator, falsey);
}
// Retrieve the next value. If the iteration ends, we're done here.
- done = Value::fromReturnedValue(Runtime::method_iteratorNext(scope.engine, iterator, nextValue));
+ done = Value::fromReturnedValue(Runtime::IteratorNext::call(scope.engine, iterator, nextValue));
CHECK_EXCEPTION();
if (done->toBoolean()) {
if (ArrayObject *ao = a->as<ArrayObject>()) {
@@ -257,7 +257,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
mapArguments[1] = Value::fromDouble(k);
mappedValue = mapfn->call(thisArg, mapArguments, 2);
if (scope.engine->hasException)
- return Runtime::method_iteratorClose(scope.engine, iterator, Value::fromBoolean(false));
+ return Runtime::IteratorClose::call(scope.engine, iterator, Value::fromBoolean(false));
} else {
mappedValue = *nextValue;
}
@@ -271,7 +271,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
if (scope.engine->hasException) {
ScopedValue falsey(scope, Encode(false));
- return Runtime::method_iteratorClose(scope.engine, iterator, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iterator, falsey);
}
k++;
@@ -387,7 +387,7 @@ ReturnedValue ArrayPrototype::method_toLocaleString(const FunctionObject *b, con
v = instance->get(k);
if (v->isNullOrUndefined())
continue;
- v = Runtime::method_callElement(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
+ v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
s = v->toString(scope.engine);
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4calldata_p.h b/src/qml/jsruntime/qv4calldata_p.h
new file mode 100644
index 0000000000..8487872bf5
--- /dev/null
+++ b/src/qml/jsruntime/qv4calldata_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4CALLDATA_P_H
+#define QV4CALLDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4value_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct CallData
+{
+ enum Offsets {
+ Function = 0,
+ Context = 1,
+ Accumulator = 2,
+ This = 3,
+ NewTarget = 4,
+ Argc = 5,
+
+ LastOffset = Argc,
+ OffsetCount = LastOffset + 1
+ };
+
+ Value function;
+ Value context;
+ Value accumulator;
+ Value thisObject;
+ Value newTarget;
+ Value _argc;
+
+ int argc() const {
+ Q_ASSERT(_argc.isInteger());
+ return _argc.int_32();
+ }
+
+ void setArgc(int argc) {
+ Q_ASSERT(argc >= 0);
+ _argc.setInt_32(argc);
+ }
+
+ inline ReturnedValue argument(int i) const {
+ return i < argc() ? args[i].asReturnedValue() : Value::undefinedValue().asReturnedValue();
+ }
+
+ Value args[1];
+
+ static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); }
+};
+
+Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
+Q_STATIC_ASSERT(offsetof(CallData, function ) == CallData::Function * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, context ) == CallData::Context * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, accumulator) == CallData::Accumulator * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, thisObject ) == CallData::This * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, newTarget ) == CallData::NewTarget * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, _argc ) == CallData::Argc * sizeof(Value));
+Q_STATIC_ASSERT(offsetof(CallData, args ) == 6 * sizeof(Value));
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4CALLDATA_P_H
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 94b1a9fb73..b3bcfe21d5 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -81,17 +81,17 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b
return c;
}
-Heap::CallContext *ExecutionContext::cloneBlockContext(Heap::CallContext *context)
+Heap::CallContext *ExecutionContext::cloneBlockContext(ExecutionEngine *engine,
+ Heap::CallContext *callContext)
{
- uint nLocals = context->locals.alloc;
+ uint nLocals = callContext->locals.alloc;
size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
- ExecutionEngine *v4 = context->internalClass->engine;
- Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, context->internalClass);
- memcpy(c, context, requiredMemory);
+ Heap::CallContext *c = engine->memoryManager->allocManaged<CallContext>(
+ requiredMemory, callContext->internalClass);
+ memcpy(c, callContext, requiredMemory);
return c;
-
}
Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
@@ -128,7 +128,7 @@ Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
return c;
}
-Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with)
+Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with) const
{
Heap::ExecutionContext *c = engine()->memoryManager->alloc<ExecutionContext>(Heap::ExecutionContext::Type_WithContext);
c->outer.set(engine(), d());
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 5cd2f9ddf0..75fa2d08e6 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -150,9 +150,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
V4_INTERNALCLASS(ExecutionContext)
static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex);
- static Heap::CallContext *cloneBlockContext(Heap::CallContext *context);
+ static Heap::CallContext *cloneBlockContext(ExecutionEngine *engine,
+ Heap::CallContext *callContext);
static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame);
- Heap::ExecutionContext *newWithContext(Heap::Object *with);
+ Heap::ExecutionContext *newWithContext(Heap::Object *with) const;
static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName);
void createMutableBinding(String *name, bool deletable);
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 5b9934282c..a87eb92caf 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -96,7 +96,7 @@ struct DateObject: Object {
double date() const { return d()->date; }
void setDate(double date) { d()->date = date; }
- QDateTime toQDateTime() const;
+ Q_QML_PRIVATE_EXPORT QDateTime toQDateTime() const;
};
template<>
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index f5c5c49f56..b04a879c7f 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -38,9 +38,6 @@
****************************************************************************/
#include <qv4engine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
@@ -51,8 +48,9 @@
#include <QDir>
#include <QFileInfo>
#include <QLoggingCategory>
-
-#ifndef V4_BOOTSTRAP
+#if QT_CONFIG(regularexpression)
+#include <QRegularExpression>
+#endif
#include <qv4qmlcontext_p.h>
#include <qv4value_p.h>
@@ -104,7 +102,6 @@
#include "qv4dataview_p.h"
#include "qv4promiseobject_p.h"
#include "qv4typedarray_p.h"
-#include <private/qv8engine_p.h>
#include <private/qjsvalue_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
@@ -112,9 +109,16 @@
#include <private/qqmllistwrapper_p.h>
#include <private/qqmllist_p.h>
#include <private/qqmltypeloader_p.h>
+#include <private/qqmlmemoryprofiler_p.h>
+#include <private/qqmlbuiltinfunctions_p.h>
#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
#endif
+#if QT_CONFIG(qml_xml_http_request)
+#include <private/qv4domerrors_p.h>
+#include <private/qqmlxmlhttprequest_p.h>
+#endif
+#include <private/qv4sqlerrors_p.h>
#include <qqmlfile.h>
#if USE(PTHREADS)
@@ -131,16 +135,12 @@
#include <valgrind/memcheck.h>
#endif
-#endif // #ifndef V4_BOOTSTRAP
+Q_DECLARE_METATYPE(QList<int>)
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcTracingAll, "qt.v4.tracing.all")
-
using namespace QV4;
-#ifndef V4_BOOTSTRAP
-
static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
@@ -150,6 +150,43 @@ ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const
qint32 ExecutionEngine::maxCallDepth = -1;
+template <typename ReturnType>
+ReturnType convertJSValueToVariantType(const QJSValue &value)
+{
+ return value.toVariant().value<ReturnType>();
+}
+
+static void saveJSValue(QDataStream &stream, const void *data)
+{
+ const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
+ quint32 isNullOrUndefined = 0;
+ if (jsv->isNull())
+ isNullOrUndefined |= 0x1;
+ if (jsv->isUndefined())
+ isNullOrUndefined |= 0x2;
+ stream << isNullOrUndefined;
+ if (!isNullOrUndefined)
+ reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
+}
+
+static void restoreJSValue(QDataStream &stream, void *data)
+{
+ QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
+
+ quint32 isNullOrUndefined;
+ stream >> isNullOrUndefined;
+
+ if (isNullOrUndefined & 0x1) {
+ *jsv = QJSValue(QJSValue::NullValue);
+ } else if (isNullOrUndefined & 0x2) {
+ *jsv = QJSValue();
+ } else {
+ QVariant v;
+ v.load(stream);
+ QJSValuePrivate::setVariant(jsv, v);
+ }
+}
+
ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -157,14 +194,17 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
, jsStack(new WTF::PageAllocation)
, gcStack(new WTF::PageAllocation)
, globalCode(nullptr)
- , v8Engine(nullptr)
, publicEngine(jsEngine)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(nullptr)
, m_multiplyWrappedQObjects(nullptr)
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+#if QT_CONFIG(qml_jit)
, m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
#endif
+#if QT_CONFIG(qml_xml_http_request)
+ , m_xmlHttpRequestData(nullptr)
+#endif
+ , m_qmlEngine(nullptr)
{
memoryManager = new QV4::MemoryManager(this);
@@ -651,18 +691,28 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
pd->set = thrower();
functionPrototype()->insertMember(id_caller(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
functionPrototype()->insertMember(id_arguments(), pd, Attr_Accessor|Attr_ReadOnly_ButConfigurable);
+
+ QML_MEMORY_SCOPE_STRING("QV4Engine::QV4Engine");
+ qMetaTypeId<QJSValue>();
+ qMetaTypeId<QList<int> >();
+
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
+ QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
+ QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
+ QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
+ QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
+
+ QV4::QObjectWrapper::initializeBindings(this);
+
+ m_delayedCallQueue.init(this);
}
ExecutionEngine::~ExecutionEngine()
{
- if (Q_UNLIKELY(lcTracingAll().isDebugEnabled())) {
- for (auto cu : compilationUnits) {
- for (auto f : qAsConst(cu->runtimeFunctions))
- qCDebug(lcTracingAll).noquote().nospace() << f->traceInfoToString();
- }
- }
-
modules.clear();
+ qDeleteAll(m_extensionData);
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = nullptr;
delete identifierTable;
@@ -679,6 +729,11 @@ ExecutionEngine::~ExecutionEngine()
delete jsStack;
gcStack->deallocate();
delete gcStack;
+
+#if QT_CONFIG(qml_xml_http_request)
+ qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
+ m_xmlHttpRequestData = nullptr;
+#endif
}
ExecutionContext *ExecutionEngine::currentContext() const
@@ -860,6 +915,13 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
return memoryManager->allocate<RegExpObject>(re);
}
+#if QT_CONFIG(regularexpression)
+Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
+{
+ return memoryManager->allocate<RegExpObject>(re);
+}
+#endif
+
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
return ErrorObject::create<ErrorObject>(this, value, errorCtor());
@@ -1072,6 +1134,12 @@ extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext)
return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext));
}
+extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine)
+{
+ auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine));
+ return v4StackTrace(engine->currentContext());
+}
+
QUrl ExecutionEngine::resolvedUrl(const QString &file)
{
QUrl src(file);
@@ -1269,6 +1337,7 @@ static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &va
const QByteArray &targetType,
void **result);
static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst);
+static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst);
static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap);
static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &value)
{
@@ -1305,7 +1374,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
&& !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
- return qVariantFromValue<QObject *>(wrapper->object());
+ return QVariant::fromValue<QObject *>(wrapper->object());
} else if (object->as<QV4::QQmlContextWrapper>()) {
return QVariant();
} else if (QV4::QQmlTypeWrapper *w = object->as<QV4::QQmlTypeWrapper>()) {
@@ -1336,7 +1405,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
}
}
- return qVariantFromValue<QList<QObject*> >(list);
+ return QVariant::fromValue<QList<QObject*> >(list);
} else if (typeHint == QMetaType::QJsonArray) {
return QVariant::fromValue(QV4::JsonObject::toJsonArray(a));
}
@@ -1379,8 +1448,13 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
QV4::ScopedObject o(scope, value);
Q_ASSERT(o);
- if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
+ if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>()) {
+#if QT_CONFIG(regularexpression)
+ if (typeHint != QMetaType::QRegExp)
+ return re->toQRegularExpression();
+#endif
return re->toQRegExp();
+ }
if (createJSValueForObjects)
return QVariant::fromValue(QJSValue(scope.engine, o->asReturnedValue()));
@@ -1442,35 +1516,6 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V
return result;
}
-static QV4::ReturnedValue arrayFromVariantList(QV4::ExecutionEngine *e, const QVariantList &list)
-{
- QV4::Scope scope(e);
- QV4::ScopedArrayObject a(scope, e->newArrayObject());
- int len = list.count();
- a->arrayReserve(len);
- QV4::ScopedValue v(scope);
- for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = scope.engine->fromVariant(list.at(ii))));
-
- a->setArrayLengthUnchecked(len);
- return a.asReturnedValue();
-}
-
-static QV4::ReturnedValue objectFromVariantMap(QV4::ExecutionEngine *e, const QVariantMap &map)
-{
- QV4::Scope scope(e);
- QV4::ScopedObject o(scope, e->newObject());
- QV4::ScopedString s(scope);
- QV4::ScopedValue v(scope);
- for (QVariantMap::const_iterator iter = map.begin(), cend = map.end(); iter != cend; ++iter) {
- s = e->newString(iter.key());
- o->put(s, (v = e->fromVariant(iter.value())));
- }
- return o.asReturnedValue();
-}
-
-Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
-
QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
{
int type = variant.userType();
@@ -1520,6 +1565,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr)));
case QMetaType::QRegExp:
return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
+#if QT_CONFIG(regularexpression)
+ case QMetaType::QRegularExpression:
+ return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr)));
+#endif
case QMetaType::QObjectStar:
return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
#if QT_CONFIG(qml_sequence_object)
@@ -1534,9 +1583,9 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
}
#endif
case QMetaType::QVariantList:
- return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
+ return variantListToJS(this, *reinterpret_cast<const QVariantList *>(ptr));
case QMetaType::QVariantMap:
- return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
+ return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(ptr));
case QMetaType::QJsonValue:
return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr));
case QMetaType::QJsonObject:
@@ -1597,6 +1646,11 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return retn->asReturnedValue();
#endif
+ if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
+ QSequentialIterable lst = variant.value<QSequentialIterable>();
+ return sequentialIterableToJS(this, lst);
+ }
+
if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type))
return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type);
}
@@ -1661,9 +1715,8 @@ static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVarian
s = v4->newIdentifier(it.key());
key = s->propertyKey();
v = variantToJS(v4, it.value());
- uint idx = key->asArrayIndex();
- if (idx < UINT_MAX)
- o->arraySet(idx, v);
+ if (key->isArrayIndex())
+ o->arraySet(key->asArrayIndex(), v);
else
o->insertMember(s, v);
}
@@ -1676,99 +1729,13 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
{
Q_ASSERT(data != nullptr);
- // check if it's one of the types we know
- switch (QMetaType::Type(type)) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- return QV4::Encode::undefined();
- case QMetaType::Nullptr:
- case QMetaType::VoidStar:
- return QV4::Encode::null();
- case QMetaType::Bool:
- return QV4::Encode(*reinterpret_cast<const bool*>(data));
- case QMetaType::Int:
- return QV4::Encode(*reinterpret_cast<const int*>(data));
- case QMetaType::UInt:
- return QV4::Encode(*reinterpret_cast<const uint*>(data));
- case QMetaType::LongLong:
- return QV4::Encode(double(*reinterpret_cast<const qlonglong*>(data)));
- case QMetaType::ULongLong:
-#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
-#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
- return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
- return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
-#else
- return QV4::Encode(double(*reinterpret_cast<const qulonglong*>(data)));
-#endif
- case QMetaType::Double:
- return QV4::Encode(*reinterpret_cast<const double*>(data));
- case QMetaType::QString:
- return newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
- case QMetaType::QByteArray:
- return newArrayBuffer(*reinterpret_cast<const QByteArray*>(data))->asReturnedValue();
- case QMetaType::Float:
- return QV4::Encode(*reinterpret_cast<const float*>(data));
- case QMetaType::Short:
- return QV4::Encode((int)*reinterpret_cast<const short*>(data));
- case QMetaType::UShort:
- return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(data));
- case QMetaType::Char:
- return QV4::Encode((int)*reinterpret_cast<const char*>(data));
- case QMetaType::UChar:
- return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(data));
- case QMetaType::QChar:
- return QV4::Encode((int)(*reinterpret_cast<const QChar*>(data)).unicode());
- case QMetaType::QStringList:
- return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(data)));
- case QMetaType::QVariantList:
- return variantListToJS(this, *reinterpret_cast<const QVariantList *>(data));
- case QMetaType::QVariantMap:
- return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(data));
- case QMetaType::QDateTime:
- return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(data)));
- case QMetaType::QDate:
- return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(data))));
- case QMetaType::QRegExp:
- return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(data)));
- case QMetaType::QObjectStar:
- return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data));
- case QMetaType::QVariant:
+ QVariant variant(type, data);
+ if (QMetaType::Type(variant.type()) == QMetaType::QVariant) {
+ // unwrap it: this is tested in QJSEngine, and makes the most sense for
+ // end-user code too.
return variantToJS(this, *reinterpret_cast<const QVariant*>(data));
- case QMetaType::QJsonValue:
- return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(data));
- case QMetaType::QJsonObject:
- return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(data));
- case QMetaType::QJsonArray:
- return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(data));
- default:
- if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::convertedToValue(this, *reinterpret_cast<const QJSValue*>(data));
- } else {
- QByteArray typeName = QMetaType::typeName(type);
- if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
- return QV4::Encode::null();
- }
- QMetaType mt(type);
- if (auto metaObject = mt.metaObject()) {
- auto flags = mt.flags();
- if (flags & QMetaType::IsGadget) {
- return QV4::QQmlValueTypeWrapper::create(this, QVariant(type, data), metaObject, type);
- } else if (flags & QMetaType::PointerToQObject) {
- return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data));
- }
- }
- if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
- auto v = QVariant(type, data);
- QSequentialIterable lst = v.value<QSequentialIterable>();
- return sequentialIterableToJS(this, lst);
- }
- // Fall back to wrapping in a QVariant.
- return QV4::Encode(newVariantObject(QVariant(type, data)));
- }
}
- Q_UNREACHABLE();
- return 0;
+ return fromVariant(variant);
}
ReturnedValue ExecutionEngine::global()
@@ -1796,7 +1763,8 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(con
QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp)
{
QList<QQmlJS::DiagnosticMessage> diagnostics;
- auto unit = compileModule(/*debugMode*/debugger() != nullptr, url.toString(), sourceCode, sourceTimeStamp, &diagnostics);
+ auto unit = Compiler::Codegen::compileModule(/*debugMode*/debugger() != nullptr, url.toString(),
+ sourceCode, sourceTimeStamp, &diagnostics);
for (const QQmlJS::DiagnosticMessage &m : diagnostics) {
if (m.isError()) {
throwSyntaxError(m.message, url.toString(), m.loc.startLine, m.loc.startColumn);
@@ -1809,52 +1777,6 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(con
return unit;
}
-#endif // ifndef V4_BOOTSTRAP
-
-QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(bool debugMode, const QString &url, const QString &sourceCode,
- const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics)
-{
- QQmlJS::Engine ee;
- QQmlJS::Lexer lexer(&ee);
- lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);
- QQmlJS::Parser parser(&ee);
-
- const bool parsed = parser.parseModule();
-
- if (diagnostics)
- *diagnostics = parser.diagnosticMessages();
-
- if (!parsed)
- return nullptr;
-
- QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode());
- if (!moduleNode) {
- // if parsing was successful, and we have no module, then
- // the file was empty.
- if (diagnostics)
- diagnostics->clear();
- return nullptr;
- }
-
- using namespace QV4::Compiler;
- Compiler::Module compilerModule(debugMode);
- compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
- compilerModule.sourceTimeStamp = sourceTimeStamp;
- JSUnitGenerator jsGenerator(&compilerModule);
- Codegen cg(&jsGenerator, /*strictMode*/true);
- cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule);
- auto errors = cg.errors();
- if (diagnostics)
- *diagnostics << errors;
-
- if (!errors.isEmpty())
- return nullptr;
-
- return cg.generateCompilationUnit();
-}
-
-#ifndef V4_BOOTSTRAP
-
void ExecutionEngine::injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit)
{
// Injection can happen from the QML type loader thread for example, but instantiation and
@@ -1898,6 +1820,133 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::loadModule(const
return newModule;
}
+void ExecutionEngine::initQmlGlobalObject()
+{
+ initializeGlobal();
+ freezeObject(*globalObject);
+}
+
+void ExecutionEngine::initializeGlobal()
+{
+ QV4::Scope scope(this);
+ QV4::GlobalExtensions::init(globalObject, QJSEngine::AllExtensions);
+
+ QV4::ScopedObject qt(scope, memoryManager->allocate<QV4::QtObject>(qmlEngine()));
+ globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
+
+#if QT_CONFIG(qml_locale)
+ QQmlLocale::registerStringLocaleCompare(this);
+ QQmlDateExtension::registerExtension(this);
+ QQmlNumberExtension::registerExtension(this);
+#endif
+
+#if QT_CONFIG(qml_xml_http_request)
+ qt_add_domexceptions(this);
+ m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
+#endif
+
+ qt_add_sqlexceptions(this);
+
+ {
+ for (uint i = 0; i < globalObject->internalClass()->size; ++i) {
+ if (globalObject->internalClass()->nameMap.at(i).isString()) {
+ QV4::PropertyKey id = globalObject->internalClass()->nameMap.at(i);
+ m_illegalNames.insert(id.toQString());
+ }
+ }
+ }
+}
+
+const QSet<QString> &ExecutionEngine::illegalNames() const
+{
+ return m_illegalNames;
+}
+
+void ExecutionEngine::setQmlEngine(QQmlEngine *engine)
+{
+ m_qmlEngine = engine;
+ initQmlGlobalObject();
+}
+
+static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
+{
+ if (object->as<QV4::QObjectWrapper>())
+ return;
+
+ QV4::Scope scope(v4);
+
+ bool instanceOfObject = false;
+ QV4::ScopedObject p(scope, object->getPrototypeOf());
+ while (p) {
+ if (p->d() == v4->objectPrototype()->d()) {
+ instanceOfObject = true;
+ break;
+ }
+ p = p->getPrototypeOf();
+ }
+ if (!instanceOfObject)
+ return;
+
+ QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ if (object->internalClass() == frozen)
+ return;
+ object->setInternalClass(frozen);
+
+ QV4::ScopedObject o(scope);
+ for (uint i = 0; i < frozen->size; ++i) {
+ if (!frozen->nameMap.at(i).isStringOrSymbol())
+ continue;
+ o = *object->propertyData(i);
+ if (o)
+ freeze_recursive(v4, o);
+ }
+}
+
+void ExecutionEngine::freezeObject(const QV4::Value &value)
+{
+ QV4::Scope scope(this);
+ QV4::ScopedObject o(scope, value);
+ freeze_recursive(this, o);
+}
+
+void ExecutionEngine::startTimer(const QString &timerName)
+{
+ if (!m_time.isValid())
+ m_time.start();
+ m_startedTimers[timerName] = m_time.elapsed();
+}
+
+qint64 ExecutionEngine::stopTimer(const QString &timerName, bool *wasRunning)
+{
+ if (!m_startedTimers.contains(timerName)) {
+ *wasRunning = false;
+ return 0;
+ }
+ *wasRunning = true;
+ qint64 startedAt = m_startedTimers.take(timerName);
+ return m_time.elapsed() - startedAt;
+}
+
+int ExecutionEngine::consoleCountHelper(const QString &file, quint16 line, quint16 column)
+{
+ const QString key = file + QString::number(line) + QString::number(column);
+ int number = m_consoleCount.value(key, 0);
+ number++;
+ m_consoleCount.insert(key, number);
+ return number;
+}
+
+void ExecutionEngine::setExtensionData(int index, Deletable *data)
+{
+ if (m_extensionData.count() <= index)
+ m_extensionData.resize(index + 1);
+
+ if (m_extensionData.at(index))
+ delete m_extensionData.at(index);
+
+ m_extensionData[index] = data;
+}
+
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
@@ -1973,6 +2022,13 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
+#if QT_CONFIG(regularexpression)
+ case QMetaType::QRegularExpression:
+ if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
+ *reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression();
+ return true;
+ } break;
+#endif
case QMetaType::QObjectStar: {
const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
if (qobjectWrapper || value->isNull()) {
@@ -2137,6 +2193,23 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &v
return wrapper->object();
}
-#endif // ifndef V4_BOOTSTRAP
+struct QV4EngineRegistrationData
+{
+ QV4EngineRegistrationData() : extensionCount(0) {}
+
+ QMutex mutex;
+ int extensionCount;
+};
+Q_GLOBAL_STATIC(QV4EngineRegistrationData, registrationData);
+
+QMutex *ExecutionEngine::registrationMutex()
+{
+ return &registrationData()->mutex;
+}
+
+int ExecutionEngine::registerExtension()
+{
+ return registrationData()->extensionCount++;
+}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 86367c0ece..0d113754c0 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -53,25 +53,82 @@
#include "qv4global_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4stackframe_p.h"
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
#include <private/qqmlrefcount_p.h>
#include <private/qqmljsengine_p.h>
+#include <private/qqmldelayedcallqueue_p.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qmutex.h>
-#ifndef V4_BOOTSTRAP
-# include "qv4function_p.h"
-# include <private/qv8engine_p.h>
-# include <private/qv4compileddata_p.h>
-#endif
+#include "qv4function_p.h"
+#include <private/qv4compileddata_p.h>
namespace WTF {
class BumpPointerAllocator;
class PageAllocation;
}
+#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
+ static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
+ { \
+ static int extensionId = -1; \
+ if (extensionId == -1) { \
+ QV4::ExecutionEngine::registrationMutex()->lock(); \
+ if (extensionId == -1) \
+ extensionId = QV4::ExecutionEngine::registerExtension(); \
+ QV4::ExecutionEngine::registrationMutex()->unlock(); \
+ } \
+ dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
+ if (!rv) { \
+ rv = new dataclass(engine); \
+ engine->setExtensionData(extensionId, rv); \
+ } \
+ return rv; \
+ } \
+
+
QT_BEGIN_NAMESPACE
-class QV8Engine;
+namespace QV4 { struct QObjectMethod; }
+
+// Used to allow a QObject method take and return raw V4 handles without having to expose
+// 48 in the public API.
+// Use like this:
+// class MyClass : public QObject {
+// Q_OBJECT
+// ...
+// Q_INVOKABLE void myMethod(QQmlV4Function*);
+// };
+// The QQmlV8Function - and consequently the arguments and return value - only remains
+// valid during the call. If the return value isn't set within myMethod(), the will return
+// undefined.
+
+class QQmlV4Function
+{
+public:
+ int length() const { return callData->argc(); }
+ QV4::ReturnedValue operator[](int idx) const { return (idx < callData->argc() ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
+ void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
+ QV4::ExecutionEngine *v4engine() const { return e; }
+private:
+ friend struct QV4::QObjectMethod;
+ QQmlV4Function();
+ QQmlV4Function(const QQmlV4Function &);
+ QQmlV4Function &operator=(const QQmlV4Function &);
+
+ QQmlV4Function(QV4::CallData *callData, QV4::Value *retVal, QV4::ExecutionEngine *e)
+ : callData(callData), retVal(retVal), e(e)
+ {
+ callData->thisObject = QV4::Encode::undefined();
+ }
+
+ QV4::CallData *callData;
+ QV4::Value *retVal;
+ QV4::ExecutionEngine *e;
+};
+
class QQmlError;
class QJSEngine;
class QQmlEngine;
@@ -128,14 +185,8 @@ public:
Function *globalCode;
-#ifdef V4_BOOTSTRAP
- QJSEngine *jsEngine() const;
- QQmlEngine *qmlEngine() const;
-#else // !V4_BOOTSTRAP
QJSEngine *jsEngine() const { return publicEngine; }
- QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; }
-#endif // V4_BOOTSTRAP
- QV8Engine *v8Engine;
+ QQmlEngine *qmlEngine() const { return m_qmlEngine; }
QJSEngine *publicEngine;
enum JSObjects {
@@ -438,9 +489,7 @@ public:
Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
-#ifndef V4_BOOTSTRAP
QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
-#endif
quint32 m_engineId;
@@ -464,7 +513,7 @@ public:
// but any time a QObject is wrapped a second time in another engine, we have to do
// bookkeeping.
MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+#if QT_CONFIG(qml_jit)
const bool m_canAllocateExecutableMemory;
#endif
@@ -520,6 +569,9 @@ public:
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
Heap::RegExpObject *newRegExpObject(RegExp *re);
Heap::RegExpObject *newRegExpObject(const QRegExp &re);
+#if QT_CONFIG(regularexpression)
+ Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
+#endif
Heap::Object *newErrorObject(const Value &value);
Heap::Object *newErrorObject(const QString &message);
@@ -592,7 +644,7 @@ public:
bool canJIT(Function *f = nullptr)
{
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+#if QT_CONFIG(qml_jit)
if (!m_canAllocateExecutableMemory)
return false;
if (f)
@@ -605,11 +657,47 @@ public:
}
QV4::ReturnedValue global();
+ void initQmlGlobalObject();
+ void initializeGlobal();
+
+ void freezeObject(const QV4::Value &value);
+
+ // Return the list of illegal id names (the names of the properties on the global object)
+ const QSet<QString> &illegalNames() const;
+
+#if QT_CONFIG(qml_xml_http_request)
+ void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
+#endif
+
+ void setQmlEngine(QQmlEngine *engine);
+
+ QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
+
+ // used for console.time(), console.timeEnd()
+ void startTimer(const QString &timerName);
+ qint64 stopTimer(const QString &timerName, bool *wasRunning);
+
+ // used for console.count()
+ int consoleCountHelper(const QString &file, quint16 line, quint16 column);
+
+ struct Deletable {
+ virtual ~Deletable() {}
+ };
+
+ static QMutex *registrationMutex();
+ static int registerExtension();
+
+ void setExtensionData(int, Deletable *);
+ Deletable *extensionData(int index) const
+ {
+ if (index < m_extensionData.count())
+ return m_extensionData[index];
+ else
+ return nullptr;
+ }
double localTZA = 0.0; // local timezone, initialized at startup
- static QQmlRefPointer<CompiledData::CompilationUnit> compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
-#ifndef V4_BOOTSTRAP
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url);
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
@@ -618,29 +706,33 @@ public:
void injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit);
QQmlRefPointer<CompiledData::CompilationUnit> moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const;
QQmlRefPointer<CompiledData::CompilationUnit> loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr);
-#endif
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
+ QSet<QString> m_illegalNames;
int jitCallCountThreshold;
// used by generated Promise objects to handle 'then' events
QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler;
-};
-// This is a trick to tell the code generators that functions taking a NoThrowContext won't
-// throw exceptions and therefore don't need a check after the call.
-#ifndef V4_BOOTSTRAP
-struct NoThrowEngine : public ExecutionEngine
-{
-};
-#else
-struct NoThrowEngine;
+#if QT_CONFIG(qml_xml_http_request)
+ void *m_xmlHttpRequestData;
#endif
+ QQmlEngine *m_qmlEngine;
+
+ QQmlDelayedCallQueue m_delayedCallQueue;
+
+ QElapsedTimer m_time;
+ QHash<QString, qint64> m_startedTimers;
+
+ QHash<QString, quint32> m_consoleCount;
+
+ QVector<Deletable *> m_extensionData;
+};
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index b5cfea8863..00876c71a2 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -69,9 +69,20 @@ struct Q_QML_EXPORT EngineBase {
CppStackFrame *currentStackFrame = nullptr;
Value *jsStackTop = nullptr;
+
+ // The JIT expects hasException and isInterrupted to be in the same 32bit word in memory.
quint8 hasException = false;
- quint8 writeBarrierActive = false;
+ // isInterrupted is expected to be set from a different thread
+#if defined(Q_ATOMIC_INT8_IS_SUPPORTED)
+ QAtomicInteger<quint8> isInterrupted = false;
quint16 unused = 0;
+#elif defined(Q_ATOMIC_INT16_IS_SUPPORTED)
+ quint8 unused = 0;
+ QAtomicInteger<quint16> isInterrupted = false;
+#else
+# error V4 needs either 8bit or 16bit atomics.
+#endif
+
quint8 isExecutingInRegExpJIT = false;
quint8 padding[3];
MemoryManager *memoryManager = nullptr;
@@ -137,6 +148,10 @@ Q_STATIC_ASSERT(offsetof(EngineBase, hasException) == offsetof(EngineBase, jsSta
Q_STATIC_ASSERT(offsetof(EngineBase, memoryManager) == offsetof(EngineBase, hasException) + 8);
Q_STATIC_ASSERT(offsetof(EngineBase, runtime) == offsetof(EngineBase, memoryManager) + QT_POINTER_SIZE);
+#ifndef V4_BOOTSTRAP
+Q_STATIC_ASSERT(offsetof(EngineBase, isInterrupted) + sizeof(EngineBase::isInterrupted) <= offsetof(EngineBase, hasException) + 4);
+#endif
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 1bd4329fe8..debdf23d27 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -75,19 +75,12 @@ ReturnedValue Function::call(const Value *thisObject, const Value *argv, int arg
Function *Function::create(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
{
- quint16 traceSlotCount = 0;
-#if QT_CONFIG(qml_tracing)
- traceSlotCount = function->nTraceInfos == CompiledData::Function::NoTracing()
- ? 1
- : function->nTraceInfos;
-#endif
- quint8 *storage = new quint8[sizeof(Function) + traceSlotCount];
- return new(storage) Function(engine, unit, function);
+ return new Function(engine, unit, function);
}
void Function::destroy()
{
- delete[] reinterpret_cast<quint8 *>(this);
+ delete this;
}
Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function)
@@ -111,13 +104,6 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
internalClass = ic->d();
nFormals = compiledFunction->nFormals;
-
-#if QT_CONFIG(qml_tracing)
- if (tracingEnabled()) {
- for (uint i = 0; i < function->nTraceInfos; ++i)
- *traceInfo(i) = 0;
- }
-#endif
}
Function::~Function()
@@ -188,22 +174,4 @@ QQmlSourceLocation Function::sourceLocation() const
return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column);
}
-QString Function::traceInfoToString()
-{
- QString info = QLatin1String("=== Trace information for ") + name()->toQString() + QLatin1Char(':');
- if (!tracingEnabled())
- return info + QStringLiteral(" disabled. Interpreter call count: %1\n").arg(interpreterCallCount);
- if (compiledFunction->nTraceInfos == 0)
- return info + QLatin1String(" none.\n");
-
- info += QLatin1Char('\n');
- for (uint i = 0, ei = compiledFunction->nTraceInfos; i < ei; ++i) {
- auto bits = QString::number(*traceInfo(i), 2);
- if (bits.size() < 8)
- bits.prepend(QString(8 - bits.size(), '0'));
- info += QStringLiteral(" %1: %2\n").arg(QString::number(i), bits);
- }
- return info;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index f8125a58f8..01b212370d 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -123,31 +123,6 @@ public:
return nullptr;
return compilationUnit->runtimeFunctions[compiledFunction->nestedFunctionIndex];
}
-
- Q_NEVER_INLINE QString traceInfoToString();
-
- quint8 *traceInfo(uint i)
- {
-#if QT_CONFIG(qml_tracing)
- Q_ASSERT((tracingEnabled() && i < traceInfoCount()) || (i == 0));
- return reinterpret_cast<quint8 *>(this) + sizeof(Function) + i;
-#else
- Q_UNUSED(i);
- return nullptr;
-#endif
- }
-
- quint32 traceInfoCount() const
- { return compiledFunction->nTraceInfos; }
-
- bool tracingEnabled() const
- {
-#if QT_CONFIG(qml_tracing)
- return traceInfoCount() != CompiledData::Function::NoTracing();
-#else
- return false;
-#endif
- }
};
}
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index e03d49c74d..4fee26f341 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -87,11 +87,11 @@ DECLARE_HEAP_OBJECT(FunctionObject, Object) {
}
Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name, VTable::Call call);
- void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr);
- void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr);
- void init(QV4::ExecutionContext *scope, const QString &name);
- void init();
- void destroy();
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr);
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr);
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, const QString &name);
+ Q_QML_PRIVATE_EXPORT void init();
+ Q_QML_PRIVATE_EXPORT void destroy();
void setFunction(Function *f);
@@ -260,7 +260,7 @@ struct FunctionPrototype: FunctionObject
static ReturnedValue method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
-struct IndexedBuiltinFunction : FunctionObject
+struct Q_QML_PRIVATE_EXPORT IndexedBuiltinFunction : FunctionObject
{
V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index d47393b3bb..42b6edb6e2 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -82,53 +82,9 @@ inline bool isfinite(double d) { return _finite(d); }
inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#endif
-// Decide whether to enable or disable the JIT
-
-// White list architectures
-//
-// NOTE: This should match the logic in qv4targetplatform_p.h!
-
-#if defined(Q_PROCESSOR_X86_32) && (QT_POINTER_SIZE == 4) \
- && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD))
-# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
- && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
-# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4) \
- && (defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_INTEGRITY))
-# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
-# define V4_ENABLE_JIT
-# elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
-# define V4_ENABLE_JIT
-# endif
-#elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8)
-# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY)
-# define V4_ENABLE_JIT
-# endif
-//#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
-//# define V4_ENABLE_JIT
-#endif
-
-// check FPU with double precision on ARM platform
-#if (defined(Q_PROCESSOR_ARM_64) || defined(Q_PROCESSOR_ARM_32)) && defined(V4_ENABLE_JIT) && defined(__ARM_FP) && (__ARM_FP <= 0x04)
-# undef V4_ENABLE_JIT
-#endif
-
-// Black list some platforms
-#if defined(V4_ENABLE_JIT)
-#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
-# undef V4_ENABLE_JIT
-#endif
-#endif
-
-// For debug purposes: add CONFIG+=force-compile-jit to qmake's command-line to always compile the JIT.
-#if defined(V4_FORCE_COMPILE_JIT) && !defined(V4_ENABLE_JIT)
-# define V4_ENABLE_JIT
-#endif
-
// Do certain things depending on whether the JIT is enabled or disabled
-#ifdef V4_ENABLE_JIT
+#if QT_CONFIG(qml_jit)
#define ENABLE_YARR_JIT 1
#define ENABLE_JIT 1
#define ENABLE_ASSEMBLER 1
@@ -280,20 +236,6 @@ struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-enum class ObservedTraceValues : quint8 {
- Integer = 1 << 0,
- Boolean = 1 << 1,
- Double = 1 << 2,
- Other = 1 << 3,
- TypeMask = Integer | Boolean | Double | Other,
-
- TruePathTaken = 1 << 0,
- FalsePathTaken = 1 << 1,
-
- ArrayWasAccessed = 1 << 7,
- ArrayAccessNeededFallback = 1 << 6,
-};
-
enum PropertyFlag {
Attr_Data = 0,
Attr_Accessor = 0x1,
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 5db5bd46ec..f9bc7b68c6 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -39,29 +39,19 @@
#include "qv4identifier_p.h"
#include "qv4identifiertable_p.h"
#include "qv4string_p.h"
+#include <private/qprimefornumbits_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
-
IdentifierHashData::IdentifierHashData(IdentifierTable *table, int numBits)
: size(0)
, numBits(numBits)
, identifierTable(table)
{
refCount.store(1);
- alloc = primeForNumBits(numBits);
+ alloc = qPrimeForNumBits(numBits);
entries = (IdentifierHashEntry *)malloc(alloc*sizeof(IdentifierHashEntry));
memset(entries, 0, alloc*sizeof(IdentifierHashEntry));
identifierTable->addIdentifierHash(this);
@@ -110,7 +100,7 @@ IdentifierHashEntry *IdentifierHash::addEntry(PropertyKey identifier)
if (grow) {
++d->numBits;
- int newAlloc = primeForNumBits(d->numBits);
+ int newAlloc = qPrimeForNumBits(d->numBits);
IdentifierHashEntry *newEntries = (IdentifierHashEntry *)malloc(newAlloc * sizeof(IdentifierHashEntry));
memset(newEntries, 0, newAlloc*sizeof(IdentifierHashEntry));
for (int i = 0; i < d->alloc; ++i) {
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 4305bc4647..21b47c3909 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -38,28 +38,18 @@
****************************************************************************/
#include "qv4identifiertable_p.h"
#include "qv4symbol_p.h"
+#include <private/qprimefornumbits_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
-
IdentifierTable::IdentifierTable(ExecutionEngine *engine, int numBits)
: engine(engine)
, size(0)
, numBits(numBits)
{
- alloc = primeForNumBits(numBits);
+ alloc = qPrimeForNumBits(numBits);
entriesByHash = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::StringOrSymbol *));
entriesById = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::StringOrSymbol *));
memset(entriesByHash, 0, alloc*sizeof(Heap::String *));
@@ -87,7 +77,7 @@ void IdentifierTable::addEntry(Heap::StringOrSymbol *str)
if (grow) {
++numBits;
- int newAlloc = primeForNumBits(numBits);
+ int newAlloc = qPrimeForNumBits(numBits);
Heap::StringOrSymbol **newEntries = (Heap::StringOrSymbol **)malloc(newAlloc*sizeof(Heap::String *));
memset(newEntries, 0, newAlloc*sizeof(Heap::StringOrSymbol *));
for (uint i = 0; i < alloc; ++i) {
@@ -216,9 +206,8 @@ PropertyKey IdentifierTable::asPropertyKeyImpl(const Heap::String *str)
Heap::StringOrSymbol *IdentifierTable::resolveId(PropertyKey i) const
{
- uint arrayIdx = i.asArrayIndex();
- if (arrayIdx < UINT_MAX)
- return engine->newString(QString::number(arrayIdx));
+ if (i.isArrayIndex())
+ return engine->newString(QString::number(i.asArrayIndex()));
if (!i.isValid())
return nullptr;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 36569b0a60..c0885a418c 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -72,13 +72,17 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
m_resultObject.set(v4, resultValue(v4));
#if QT_CONFIG(qml_network)
- m_network = engine->v8Engine->networkAccessManager();
+ if (QQmlEngine *qmlEngine = engine->qmlEngine()) {
+ m_network = qmlEngine->networkAccessManager();
- QNetworkRequest request;
- request.setUrl(url);
+ QNetworkRequest request;
+ request.setUrl(url);
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ } else {
+ finished();
+ }
#else
finished();
#endif
@@ -197,7 +201,7 @@ void QV4Include::finished()
}
/*
- Documented in qv8engine.cpp
+ Documented in qv4engine.cpp
*/
QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
{
@@ -214,7 +218,6 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
if (argc >= 2 && argv[1].as<QV4::FunctionObject>())
callbackFunction = argv[1];
-#if QT_CONFIG(qml_network)
QUrl url(scope.engine->resolvedUrl(argv[0].toQStringNoThrow()));
if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
@@ -225,9 +228,13 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
QV4::Scoped<QV4::QmlContext> qmlcontext(scope, scope.engine->qmlContext());
if (localFile.isEmpty()) {
+#if QT_CONFIG(qml_network)
QV4Include *i = new QV4Include(url, scope.engine, qmlcontext, callbackFunction);
result = i->result();
-
+#else
+ result = resultValue(scope.engine, NetworkError);
+ callback(callbackFunction, result);
+#endif
} else {
QScopedPointer<QV4::Script> script;
QString error;
@@ -252,12 +259,6 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
callback(callbackFunction, result);
}
-#else
- QV4::ScopedValue result(scope);
- result = resultValue(scope.engine, NetworkError);
- callback(callbackFunction, result);
-#endif
-
return result->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a10fda79f2..d597335031 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -45,27 +45,18 @@
#include "qv4identifiertable_p.h"
#include "qv4value_p.h"
#include "qv4mm_p.h"
+#include <private/qprimefornumbits_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-static const uchar prime_deltas[] = {
- 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
- 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
-};
-
-static inline int primeForNumBits(int numBits)
-{
- return (1 << numBits) + prime_deltas[numBits];
-}
-
PropertyHashData::PropertyHashData(int numBits)
: refCount(1)
, size(0)
, numBits(numBits)
{
- alloc = primeForNumBits(numBits);
+ alloc = qPrimeForNumBits(numBits);
entries = (PropertyHash::Entry *)malloc(alloc*sizeof(PropertyHash::Entry));
memset(entries, 0, alloc*sizeof(PropertyHash::Entry));
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index f8999342d1..99f425293e 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -462,11 +462,11 @@ bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object,
return false;
}
- if (l->setter == Lookup::setter0 || l->setter == Lookup::setter0Inline) {
+ if (l->setter == Lookup::setter0MemberData || l->setter == Lookup::setter0Inline) {
l->objectLookupTwoClasses.ic = first.objectLookup.ic;
l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
- l->objectLookupTwoClasses.offset = first.objectLookup.offset;
- l->objectLookupTwoClasses.offset2 = second.objectLookup.offset;
+ l->objectLookupTwoClasses.offset = first.objectLookup.index;
+ l->objectLookupTwoClasses.offset2 = second.objectLookup.index;
l->setter = setter0setter0;
return true;
}
@@ -487,11 +487,11 @@ bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c
return o->put(name, value);
}
-bool Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o && o->internalClass == l->objectLookup.ic) {
- o->setProperty(engine, l->objectLookup.offset, value);
+ o->memberData->values.set(engine, l->objectLookup.offset, value);
return true;
}
@@ -502,7 +502,7 @@ bool Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, co
{
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
if (o && o->internalClass == l->objectLookup.ic) {
- o->setInlineProperty(engine, l->objectLookup.offset, value);
+ o->setInlinePropertyWithOffset(engine, l->objectLookup.offset, value);
return true;
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 03dc5f6d3c..f2e0afd797 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Lookup {
+struct Q_QML_PRIVATE_EXPORT Lookup {
union {
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
@@ -81,8 +81,9 @@ struct Lookup {
} markDef;
struct {
Heap::InternalClass *ic;
- quintptr _unused;
- int offset;
+ quintptr unused;
+ uint index;
+ uint offset;
} objectLookup;
struct {
quintptr protoId;
@@ -92,8 +93,8 @@ struct Lookup {
struct {
Heap::InternalClass *ic;
Heap::InternalClass *ic2;
- int offset;
- int offset2;
+ uint offset;
+ uint offset2;
} objectLookupTwoClasses;
struct {
quintptr protoId;
@@ -111,12 +112,14 @@ struct Lookup {
struct {
Heap::InternalClass *newClass;
quintptr protoId;
- int offset;
+ uint offset;
+ uint unused;
} insertionLookup;
struct {
quintptr _unused;
quintptr _unused2;
uint index;
+ uint unused;
} indexedLookup;
struct {
Heap::InternalClass *ic;
@@ -187,7 +190,7 @@ struct Lookup {
static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
Q_NEVER_INLINE static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static bool setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index d85b30a056..4f22dc7330 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -54,7 +54,6 @@
#include "qv4value_p.h"
#include "qv4enginebase_p.h"
#include <private/qv4heap_p.h>
-#include <private/qv4writebarrier_p.h>
#include <private/qv4vtable_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4mapobject.cpp b/src/qml/jsruntime/qv4mapobject.cpp
index 68741e7677..90e1908a84 100644
--- a/src/qml/jsruntime/qv4mapobject.cpp
+++ b/src/qml/jsruntime/qv4mapobject.cpp
@@ -80,7 +80,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv,
if (!adder)
return scope.engine->throwTypeError();
- ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true));
+ ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true));
if (scope.hasException())
return Encode::undefined();
Q_ASSERT(iter);
@@ -89,7 +89,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv,
Value *arguments = scope.alloc(2);
ScopedValue done(scope);
forever {
- done = Runtime::method_iteratorNext(scope.engine, iter, obj);
+ done = Runtime::IteratorNext::call(scope.engine, iter, obj);
if (scope.hasException())
break;
if (done->toBoolean())
@@ -112,7 +112,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv,
break;
}
ScopedValue falsey(scope, Encode(false));
- return Runtime::method_iteratorClose(scope.engine, iter, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iter, falsey);
}
}
return a->asReturnedValue();
diff --git a/src/qml/jsruntime/qv4math_p.h b/src/qml/jsruntime/qv4math_p.h
index a60a49a811..90246c4229 100644
--- a/src/qml/jsruntime/qv4math_p.h
+++ b/src/qml/jsruntime/qv4math_p.h
@@ -66,42 +66,27 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-static inline QMLJS_READONLY ReturnedValue add_int32(int a, int b, quint8 *traceInfo = nullptr)
+static inline QMLJS_READONLY ReturnedValue add_int32(int a, int b)
{
int result;
- if (Q_UNLIKELY(add_overflow(a, b, &result))) {
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Double);
+ if (Q_UNLIKELY(add_overflow(a, b, &result)))
return Value::fromDouble(static_cast<double>(a) + b).asReturnedValue();
- }
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Integer);
return Value::fromInt32(result).asReturnedValue();
}
-static inline QMLJS_READONLY ReturnedValue sub_int32(int a, int b, quint8 *traceInfo = nullptr)
+static inline QMLJS_READONLY ReturnedValue sub_int32(int a, int b)
{
int result;
- if (Q_UNLIKELY(sub_overflow(a, b, &result))) {
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Double);
+ if (Q_UNLIKELY(sub_overflow(a, b, &result)))
return Value::fromDouble(static_cast<double>(a) - b).asReturnedValue();
- }
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Integer);
return Value::fromInt32(result).asReturnedValue();
}
-static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b, quint8 *traceInfo = nullptr)
+static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
{
int result;
- if (Q_UNLIKELY(mul_overflow(a, b, &result))) {
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Double);
+ if (Q_UNLIKELY(mul_overflow(a, b, &result)))
return Value::fromDouble(static_cast<double>(a) * b).asReturnedValue();
- }
- if (traceInfo)
- *traceInfo |= quint8(QV4::ObservedTraceValues::Integer);
return Value::fromInt32(result).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 02524b7da6..89161433ed 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -407,8 +407,8 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
{
Heap::Object *o = d();
- uint index = id.asArrayIndex();
- if (index != UINT_MAX) {
+ if (id.isArrayIndex()) {
+ const uint index = id.asArrayIndex();
Scope scope(this);
PropertyAttributes attrs;
ScopedProperty pd(scope);
@@ -432,8 +432,6 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h
break;
}
} else {
- Q_ASSERT(!id.isArrayIndex());
-
while (1) {
auto idx = o->internalClass->findValueOrGetter(id);
if (idx.isValid()) {
@@ -471,14 +469,13 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
if (d()->internalClass->vtable->getOwnProperty == Object::virtualGetOwnProperty) {
// This object standard methods in the vtable, so we can take a shortcut
// and avoid the calls to getOwnProperty and defineOwnProperty
- uint index = id.asArrayIndex();
PropertyAttributes attrs;
PropertyIndex propertyIndex{nullptr, nullptr};
- if (index != UINT_MAX) {
+ if (id.isArrayIndex()) {
if (arrayData())
- propertyIndex = arrayData()->getValueOrSetter(index, &attrs);
+ propertyIndex = arrayData()->getValueOrSetter(id.asArrayIndex(), &attrs);
} else {
auto member = internalClass()->findValueOrSetter(id);
if (member.isValid()) {
@@ -547,12 +544,11 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
if (r->internalClass()->vtable->defineOwnProperty == virtualDefineOwnProperty) {
// standard object, we can avoid some more checks
- uint index = id.asArrayIndex();
- if (index == UINT_MAX) {
+ if (id.isArrayIndex()) {
+ r->arraySet(id.asArrayIndex(), value);
+ } else {
ScopedStringOrSymbol s(scope, id.asStringOrSymbol());
r->insertMember(s, value);
- } else {
- r->arraySet(index, value);
}
return true;
}
@@ -787,8 +783,15 @@ bool Object::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine,
return lookup->setter(lookup, engine, *object, value);
} else if (idx.attrs.isData() && idx.attrs.isWritable()) {
lookup->objectLookup.ic = object->internalClass();
- lookup->objectLookup.offset = idx.index;
- lookup->setter = idx.index < object->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
+ lookup->objectLookup.index = idx.index;
+ const auto nInline = object->d()->vtable()->nInlineProperties;
+ if (idx.index < nInline) {
+ lookup->setter = Lookup::setter0Inline;
+ lookup->objectLookup.offset = idx.index + object->d()->vtable()->inlinePropertyOffset;
+ } else {
+ lookup->setter = Lookup::setter0MemberData;
+ lookup->objectLookup.offset = idx.index - nInline;
+ }
return lookup->setter(lookup, engine, *object, value);
} else {
// ### handle setter
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index bee4aadafe..52ad3ea319 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -79,21 +79,21 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
}
const Value *inlinePropertyDataWithOffset(uint indexWithOffset) const {
- Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < vtable()->inlinePropertyOffset + vtable()->nInlineProperties);
+ Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties));
return reinterpret_cast<const Value *>(this) + indexWithOffset;
}
const Value *inlinePropertyData(uint index) const {
Q_ASSERT(index < vtable()->nInlineProperties);
return reinterpret_cast<const Value *>(this) + vtable()->inlinePropertyOffset + index;
}
- void setInlineProperty(ExecutionEngine *e, uint index, Value v) {
- Q_ASSERT(index < vtable()->nInlineProperties);
- Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ void setInlinePropertyWithOffset(ExecutionEngine *e, uint indexWithOffset, Value v) {
+ Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties));
+ Value *prop = reinterpret_cast<Value *>(this) + indexWithOffset;
WriteBarrier::write(e, this, prop->data_ptr(), v.asReturnedValue());
}
- void setInlineProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
- Q_ASSERT(index < vtable()->nInlineProperties);
- Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
+ void setInlinePropertyWithOffset(ExecutionEngine *e, uint indexWithOffset, Heap::Base *b) {
+ Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties));
+ Value *prop = reinterpret_cast<Value *>(this) + indexWithOffset;
WriteBarrier::write(e, this, prop->data_ptr(), Value::fromHeapObject(b).asReturnedValue());
}
@@ -115,7 +115,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
void setProperty(ExecutionEngine *e, uint index, Value v) {
uint nInline = vtable()->nInlineProperties;
if (index < nInline) {
- setInlineProperty(e, index, v);
+ setInlinePropertyWithOffset(e, index + vtable()->inlinePropertyOffset, v);
return;
}
index -= nInline;
@@ -124,7 +124,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
void setProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
uint nInline = vtable()->nInlineProperties;
if (index < nInline) {
- setInlineProperty(e, index, b);
+ setInlinePropertyWithOffset(e, index + vtable()->inlinePropertyOffset, b);
return;
}
index -= nInline;
@@ -410,7 +410,7 @@ private:
friend struct ObjectPrototype;
};
-struct ObjectOwnPropertyKeyIterator : OwnPropertyKeyIterator
+struct Q_QML_PRIVATE_EXPORT ObjectOwnPropertyKeyIterator : OwnPropertyKeyIterator
{
uint arrayIndex = 0;
uint memberIndex = 0;
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index e9515b5b68..8707305dc2 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -74,7 +74,7 @@ struct ObjectCtor: FunctionObject
static ReturnedValue virtualCall(const FunctionObject *m, const Value *thisObject, const Value *argv, int argc);
};
-struct ObjectPrototype: Object
+struct Q_QML_PRIVATE_EXPORT ObjectPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp
index 8450655334..b32e227b58 100644
--- a/src/qml/jsruntime/qv4promiseobject.cpp
+++ b/src/qml/jsruntime/qv4promiseobject.cpp
@@ -496,7 +496,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
ScopedFunctionObject reject(scope, capability->d()->reject);
ScopedObject itemsObject(scope, argv);
- ScopedObject iteratorObject(scope, Runtime::method_getIterator(e, itemsObject, true));
+ ScopedObject iteratorObject(scope, Runtime::GetIterator::call(e, itemsObject, true));
if (!iteratorObject || scope.hasException()) {
ScopedObject error(scope);
if (scope.hasException()) {
@@ -521,7 +521,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
for (;;) {
Scope scope(e);
ScopedValue nextValue(scope);
- doneValue = Value::fromReturnedValue(Runtime::method_iteratorNext(e, iteratorObject, nextValue));
+ doneValue = Value::fromReturnedValue(Runtime::IteratorNext::call(e, iteratorObject, nextValue));
if (doneValue->toBoolean())
break;
@@ -549,7 +549,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -557,7 +557,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1)));
if (!nextPromise || scope.hasException()) {
- ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue));
+ ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
dropException(e);
@@ -579,7 +579,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(scope.engine, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(scope.engine, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -598,7 +598,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
dropException(e);
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(scope.engine, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(scope.engine, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -646,7 +646,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
ScopedFunctionObject reject(scope, capability->d()->reject);
ScopedObject itemsObject(scope, argv);
- ScopedObject iteratorObject(scope, Runtime::method_getIterator(e, itemsObject, true));
+ ScopedObject iteratorObject(scope, Runtime::GetIterator::call(e, itemsObject, true));
if (!iteratorObject) {
ScopedObject error(scope, e->newTypeErrorObject(QStringLiteral("Type error")));
reject->call(newPromise, error, 1);
@@ -657,10 +657,10 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
for (;;) {
Scope scope(e);
ScopedValue nextValue(scope);
- doneValue = Value::fromReturnedValue(Runtime::method_iteratorNext(e, iteratorObject, nextValue));
+ doneValue = Value::fromReturnedValue(Runtime::IteratorNext::call(e, iteratorObject, nextValue));
if (scope.hasException()) {
- ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue));
+ ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
dropException(e);
@@ -695,7 +695,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -703,7 +703,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1)));
if (!nextPromise || scope.hasException()) {
- ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue));
+ ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
dropException(e);
@@ -723,7 +723,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
}
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
@@ -742,7 +742,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
dropException(e);
if (!doneValue->toBoolean())
- completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue);
+ completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue);
reject->call(newPromise, completion, 1);
return newPromise.asReturnedValue();
diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
index 47867765db..b2a2ec3dea 100644
--- a/src/qml/jsruntime/qv4propertykey_p.h
+++ b/src/qml/jsruntime/qv4propertykey_p.h
@@ -113,8 +113,8 @@ public:
static PropertyKey invalid() { PropertyKey key; key.val = 0; return key; }
static PropertyKey fromArrayIndex(uint idx) { PropertyKey key; key.val = ArrayIndexMask | static_cast<quint64>(idx); return key; }
bool isStringOrSymbol() const { return isManaged() && val != 0; }
- uint asArrayIndex() const { return (isManaged() || val == 0) ? std::numeric_limits<uint>::max() : static_cast<uint>(val & 0xffffffff); }
- uint isArrayIndex() const { return !isManaged() && val != 0 && static_cast<uint>(val & 0xffffffff) != std::numeric_limits<uint>::max(); }
+ uint asArrayIndex() const { Q_ASSERT(isArrayIndex()); return static_cast<uint>(val & 0xffffffff); }
+ uint isArrayIndex() const { return !isManaged() && val != 0; }
bool isValid() const { return val != 0; }
static PropertyKey fromStringOrSymbol(Heap::StringOrSymbol *b)
{ PropertyKey key; key.setM(b); return key; }
@@ -124,7 +124,7 @@ public:
return m();
}
- bool isString() const;
+ Q_QML_EXPORT bool isString() const;
bool isSymbol() const;
bool isCanonicalNumericIndexString() const;
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 0c5226d46c..f3351f6da0 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qv4qmlcontext_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcontext_p.h>
@@ -232,17 +231,17 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
} else if (r.type.isValid()) {
if (lookup) {
if (r.type.isSingleton()) {
- QQmlEngine *e = v4->qmlEngine();
- QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo();
- siinfo->init(e);
- if (siinfo->qobjectApi(e)) {
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(v4->qmlEngine());
+ if (r.type.isQObjectSingleton() || r.type.isCompositeSingleton()) {
+ e->singletonInstance<QObject*>(r.type);
lookup->qmlContextSingletonLookup.singleton =
static_cast<Heap::Object*>(
Value::fromReturnedValue(
QQmlTypeWrapper::create(v4, nullptr, r.type)
).heapObject());
} else {
- QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
+ QJSValue singleton = e->singletonInstance<QJSValue>(r.type);
+ QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, singleton));
lookup->qmlContextSingletonLookup.singleton = o->d();
}
lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupSingleton;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6fed538fa8..095f27279f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -39,7 +39,7 @@
#include "qv4qobjectwrapper_p.h"
-#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlstaticmetaobject_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlbinding_p.h>
@@ -50,7 +50,6 @@
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
-#include <private/qv8engine_p.h>
#include <private/qv4arraybuffer_p.h>
#include <private/qv4functionobject_p.h>
@@ -165,10 +164,6 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
double v = 0;
property.readProperty(object, &v);
return QV4::Encode(v);
- } else if (property.isV4Handle()) {
- QQmlV4Handle handle;
- property.readProperty(object, &handle);
- return handle;
} else if (property.propType() == qMetaTypeId<QJSValue>()) {
QJSValue v;
property.readProperty(object, &v);
@@ -768,6 +763,8 @@ struct QObjectWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
~QObjectWrapperOwnPropertyKeyIterator() override = default;
PropertyKey next(const QV4::Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+private:
+ QSet<QByteArray> m_alreadySeen;
};
PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Property *pd, PropertyAttributes *attrs)
@@ -808,6 +805,11 @@ PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const QV4::Object *o, Pro
++propertyIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
+ // filter out duplicates due to overloads:
+ if (m_alreadySeen.contains(method.name()))
+ continue;
+ else
+ m_alreadySeen.insert(method.name());
ExecutionEngine *thatEngine = that->engine();
Scope scope(thatEngine);
ScopedString methodName(scope, thatEngine->newString(QString::fromUtf8(method.name())));
@@ -1194,15 +1196,14 @@ DEFINE_OBJECT_VTABLE(QObjectWrapper);
namespace {
-template<typename A, typename B, typename C, typename D, typename E,
- typename F, typename G, typename H>
-class MaxSizeOf8 {
+template<typename A, typename B, typename C, typename D, typename E, typename F, typename G>
+class MaxSizeOf7 {
template<typename Z, typename X>
struct SMax {
char dummy[sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X)];
};
public:
- static const size_t Size = sizeof(SMax<A, SMax<B, SMax<C, SMax<D, SMax<E, SMax<F, SMax<G, H> > > > > > >);
+ static const size_t Size = sizeof(SMax<A, SMax<B, SMax<C, SMax<D, SMax<E, SMax<F, G> > > > > >);
};
struct CallArgument {
@@ -1235,14 +1236,13 @@ private:
std::vector<QUrl> *stdVectorQUrlPtr;
std::vector<QModelIndex> *stdVectorQModelIndexPtr;
- char allocData[MaxSizeOf8<QVariant,
- QString,
- QList<QObject *>,
- QJSValue,
- QQmlV4Handle,
- QJsonArray,
- QJsonObject,
- QJsonValue>::Size];
+ char allocData[MaxSizeOf7<QVariant,
+ QString,
+ QList<QObject *>,
+ QJSValue,
+ QJsonArray,
+ QJsonObject,
+ QJsonValue>::Size];
qint64 q_for_alignment;
};
@@ -1253,7 +1253,6 @@ private:
QVariant *qvariantPtr;
QList<QObject *> *qlistPtr;
QJSValue *qjsValuePtr;
- QQmlV4Handle *handlePtr;
QJsonArray *jsonArrayPtr;
QJsonObject *jsonObjectPtr;
QJsonValue *jsonValuePtr;
@@ -1384,6 +1383,9 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
} else if (actual.as<QV4::RegExpObject>()) {
switch (conversionType) {
case QMetaType::QRegExp:
+#if QT_CONFIG(regularexpression)
+ case QMetaType::QRegularExpression:
+#endif
return 0;
default:
return 10;
@@ -1722,9 +1724,6 @@ void CallArgument::initAsType(int callType)
} else if (callType == qMetaTypeId<QList<QObject *> >()) {
type = callType;
qlistPtr = new (&allocData) QList<QObject *>();
- } else if (callType == qMetaTypeId<QQmlV4Handle>()) {
- type = callType;
- handlePtr = new (&allocData) QQmlV4Handle;
} else if (callType == QMetaType::QJsonArray) {
type = callType;
jsonArrayPtr = new (&allocData) QJsonArray();
@@ -1825,9 +1824,6 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
return false;
}
}
- } else if (callType == qMetaTypeId<QQmlV4Handle>()) {
- handlePtr = new (&allocData) QQmlV4Handle(value.asReturnedValue());
- type = callType;
} else if (callType == QMetaType::QJsonArray) {
QV4::ScopedArrayObject a(scope, value);
jsonArrayPtr = new (&allocData) QJsonArray(QV4::JsonObject::toJsonArray(a));
@@ -1952,8 +1948,6 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(scope.engine, list.at(ii))));
array->setArrayLengthUnchecked(list.count());
return array.asReturnedValue();
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- return *handlePtr;
} else if (type == QMetaType::QJsonArray) {
return QV4::JsonObject::fromJsonArray(scope.engine, *jsonArrayPtr);
} else if (type == QMetaType::QJsonObject) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 2558ede401..795bf241f2 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -55,9 +55,7 @@
#include <QtCore/qmetatype.h>
#include <QtCore/qpair.h>
#include <QtCore/qhash.h>
-#include <private/qhashedstring_p.h>
#include <private/qqmldata_p.h>
-#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
#include <private/qv4value_p.h>
diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp
index 15dcb602eb..0772770d63 100644
--- a/src/qml/jsruntime/qv4reflect.cpp
+++ b/src/qml/jsruntime/qv4reflect.cpp
@@ -148,7 +148,7 @@ ReturnedValue Reflect::method_deleteProperty(const FunctionObject *f, const Valu
if (!argc || !argv[0].isObject())
return e->throwTypeError();
- bool result = Runtime::method_deleteProperty(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
+ bool result = Runtime::DeleteProperty_NoThrow::call(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
return Encode(result);
}
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 39a2e96b45..64aba1d85c 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -50,6 +50,9 @@
#include <QtCore/QDebug>
#include <QtCore/qregexp.h>
+#if QT_CONFIG(regularexpression)
+#include <QtCore/qregularexpression.h>
+#endif
#include <cassert>
#include <typeinfo>
#include <iostream>
@@ -134,6 +137,25 @@ void Heap::RegExpObject::init(const QRegExp &re)
o->initProperties();
}
+#if QT_CONFIG(regularexpression)
+// Converts a QRegularExpression to a JS RegExp.
+// The conversion is not 100% exact since ECMA regexp and QRegularExpression
+// have different semantics/flags, but we try to do our best.
+void Heap::RegExpObject::init(const QRegularExpression &re)
+{
+ Object::init();
+
+ Scope scope(internalClass->engine);
+ Scoped<QV4::RegExpObject> o(scope, this);
+
+ const uint flags = (re.patternOptions() & QRegularExpression::CaseInsensitiveOption)
+ ? CompiledData::RegExp::RegExp_IgnoreCase
+ : CompiledData::RegExp::RegExp_NoFlags;
+ o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, re.pattern(), flags));
+ o->initProperties();
+}
+#endif
+
void RegExpObject::initProperties()
{
setProperty(Index_LastIndex, Value::fromInt32(0));
@@ -150,6 +172,20 @@ QRegExp RegExpObject::toQRegExp() const
return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2);
}
+#if QT_CONFIG(regularexpression)
+// Converts a JS RegExp to a QRegularExpression.
+// The conversion is not 100% exact since ECMA regexp and QRegularExpression
+// have different semantics/flags, but we try to do our best.
+QRegularExpression RegExpObject::toQRegularExpression() const
+{
+ QRegularExpression::PatternOptions caseSensitivity
+ = (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase)
+ ? QRegularExpression::CaseInsensitiveOption
+ : QRegularExpression::NoPatternOption;
+ return QRegularExpression(*value()->pattern, caseSensitivity);
+}
+#endif
+
QString RegExpObject::toString() const
{
QString p = *value()->pattern;
@@ -162,13 +198,6 @@ QString RegExpObject::toString() const
return p;
}
-QString RegExpObject::source() const
-{
- Scope scope(engine());
- ScopedValue s(scope, get(scope.engine->id_source()));
- return s->toQString();
-}
-
ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *str)
{
QString s = str->toQString();
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index a584404c0b..b94889e9f0 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -81,6 +81,9 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) {
void init();
void init(QV4::RegExp *value);
void init(const QRegExp &re);
+#if QT_CONFIG(regularexpression)
+ void init(const QRegularExpression &re);
+#endif
};
#define RegExpCtorMembers(class, Member) \
@@ -98,7 +101,7 @@ DECLARE_HEAP_OBJECT(RegExpCtor, FunctionObject) {
}
-struct RegExpObject: Object {
+struct Q_QML_PRIVATE_EXPORT RegExpObject: Object {
V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
V4_INTERNALCLASS(RegExpObject)
@@ -138,8 +141,16 @@ struct RegExpObject: Object {
}
QRegExp toQRegExp() const;
+#if QT_CONFIG(regularexpression)
+ QRegularExpression toQRegularExpression() const;
+#endif
QString toString() const;
- QString source() const;
+ QString source() const
+ {
+ Scope scope(engine());
+ ScopedValue s(scope, get(scope.engine->id_source()));
+ return s->toQString();
+ }
Heap::RegExp *value() const { return d()->value; }
uint flags() const { return d()->value->flags; }
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index f7c339dc26..107dfbda6f 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -38,9 +38,9 @@
****************************************************************************/
#include "qv4global_p.h"
-#include "qv4engine_p.h"
#include "qv4runtime_p.h"
#ifndef V4_BOOTSTRAP
+#include "qv4engine_p.h"
#include "qv4object_p.h"
#include "qv4objectproto_p.h"
#include "qv4globalobject_p.h"
@@ -63,7 +63,6 @@
#include "qv4qobjectwrapper_p.h"
#include "qv4symbol_p.h"
#include "qv4generatorobject_p.h"
-#include <private/qv8engine_p.h>
#endif
#include <QtCore/QDebug>
@@ -225,13 +224,6 @@ void RuntimeCounters::count(const char *func, uint tag1, uint tag2)
#ifndef V4_BOOTSTRAP
-Runtime::Runtime()
-{
-#define INIT_METHOD(returnvalue, name, args) runtimeMethods[name] = reinterpret_cast<void*>(&method_##name);
-FOR_EACH_RUNTIME_METHOD(INIT_METHOD)
-#undef INIT_METHOD
-}
-
void RuntimeHelpers::numberToString(QString *result, double num, int radix)
{
Q_ASSERT(result);
@@ -320,7 +312,7 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
result->prepend(QLatin1Char('-'));
}
-ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId)
+ReturnedValue Runtime::Closure::call(ExecutionEngine *engine, int functionId)
{
QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId];
Q_ASSERT(clos);
@@ -330,7 +322,7 @@ ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId)
return FunctionObject::createScriptFunction(current, clos)->asReturnedValue();
}
-bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base, const Value &index)
+Bool Runtime::DeleteProperty_NoThrow::call(ExecutionEngine *engine, const Value &base, const Value &index)
{
Scope scope(engine);
ScopedObject o(scope, base.toObject(engine));
@@ -344,14 +336,36 @@ bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base,
return o->deleteProperty(key);
}
-bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex)
+ReturnedValue Runtime::DeleteProperty::call(ExecutionEngine *engine, QV4::Function *function, const QV4::Value &base, const QV4::Value &index)
+{
+ if (!Runtime::DeleteProperty_NoThrow::call(engine, base, index)) {
+ if (function->isStrict())
+ engine->throwTypeError();
+ return Encode(false);
+ } else {
+ return Encode(true);
+ }
+}
+
+Bool Runtime::DeleteName_NoThrow::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).deleteProperty(name);
}
-QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &lval, const Value &rval)
+ReturnedValue Runtime::DeleteName::call(ExecutionEngine *engine, Function *function, int name)
+{
+ if (!Runtime::DeleteName_NoThrow::call(engine, name)) {
+ if (function->isStrict())
+ engine->throwTypeError();
+ return Encode(false);
+ } else {
+ return Encode(true);
+ }
+}
+
+QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Value &lval, const Value &rval)
{
// 11.8.6, 5: rval must be an Object
const Object *rhs = rval.as<Object>();
@@ -376,7 +390,7 @@ QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Val
return Encode(result->toBoolean());
}
-QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right)
+QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
Object *ro = right.objectValue();
if (!ro)
@@ -604,13 +618,12 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu
return Encode(x + y);
}
-ReturnedValue RuntimeHelpers::getTemplateObject(Function *function, int index)
+ReturnedValue Runtime::GetTemplateObject::call(Function *function, int index)
{
return function->compilationUnit->templateObjectAt(index)->asReturnedValue();
}
-
-void Runtime::method_storeProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
+void Runtime::StoreProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
QV4::Function *v4Function = engine->currentStackFrame->v4Function;
@@ -683,30 +696,8 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine,
return o->get(name);
}
-ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index)
-{
- if (index.isPositiveInt()) {
- uint idx = static_cast<uint>(index.int_32());
- if (Heap::Base *b = object.heapObject()) {
- if (b->internalClass->vtable->isObject) {
- Heap::Object *o = static_cast<Heap::Object *>(b);
- if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->values.size)
- if (!s->data(idx).isEmpty())
- return s->data(idx).asReturnedValue();
- }
- }
- }
- return getElementIntFallback(engine, object, idx);
- }
-
- return getElementFallback(engine, object, index);
-}
-
-ReturnedValue Runtime::method_loadElement_traced(ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot)
+ReturnedValue Runtime::LoadElement::call(ExecutionEngine *engine, const Value &object, const Value &index)
{
- *traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed);
if (index.isPositiveInt()) {
uint idx = static_cast<uint>(index.int_32());
if (Heap::Base *b = object.heapObject()) {
@@ -720,11 +711,9 @@ ReturnedValue Runtime::method_loadElement_traced(ExecutionEngine *engine, const
}
}
}
- *traceSlot |= quint8(ObservedTraceValues::ArrayAccessNeededFallback);
return getElementIntFallback(engine, object, idx);
}
- *traceSlot |= quint8(ObservedTraceValues::ArrayAccessNeededFallback);
return getElementFallback(engine, object, index);
}
@@ -761,7 +750,7 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val
return o->put(name, value);
}
-void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
+void Runtime::StoreElement::call(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)
{
if (index.isPositiveInt()) {
uint idx = static_cast<uint>(index.int_32());
@@ -783,31 +772,7 @@ void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object,
engine->throwTypeError();
}
-void Runtime::method_storeElement_traced(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot)
-{
- *traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed);
- if (index.isPositiveInt()) {
- uint idx = static_cast<uint>(index.int_32());
- if (Heap::Base *b = object.heapObject()) {
- if (b->internalClass->vtable->isObject) {
- Heap::Object *o = static_cast<Heap::Object *>(b);
- if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
- if (idx < s->values.size) {
- s->setData(engine, idx, value);
- return;
- }
- }
- }
- }
- }
-
- *traceSlot |= quint8(ObservedTraceValues::ArrayAccessNeededFallback);
- if (!setElementFallback(engine, object, index, value) && engine->currentStackFrame->v4Function->isStrict())
- engine->throwTypeError();
-}
-
-ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &in, int iterator)
+ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &in, int iterator)
{
Scope scope(engine);
ScopedObject o(scope, (Object *)nullptr);
@@ -830,7 +795,7 @@ ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &
return engine->newForInIteratorObject(o)->asReturnedValue();
}
-ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value &iterator, Value *value)
+ReturnedValue Runtime::IteratorNext::call(ExecutionEngine *engine, const Value &iterator, Value *value)
{
// if we throw an exception from here, return true, not undefined. This is to ensure iteratorDone is set to true
// and the stack unwinding won't close the iterator
@@ -866,7 +831,7 @@ ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value
return Encode(false);
}
-ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)
+ReturnedValue Runtime::IteratorNextForYieldStar::call(ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)
{
// the return value encodes how to continue the yield* iteration.
// true implies iteration is done, false for iteration to continue
@@ -903,7 +868,7 @@ ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine,
if (t->isUndefined()) {
// no throw method on the iterator
ScopedValue done(scope, Encode(false));
- method_iteratorClose(engine, iterator, done);
+ IteratorClose::call(engine, iterator, done);
if (engine->hasException)
return Encode::undefined();
return engine->throwTypeError();
@@ -938,7 +903,7 @@ ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine,
return Encode(false);
}
-ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value &iterator, const Value &done)
+ReturnedValue Runtime::IteratorClose::call(ExecutionEngine *engine, const Value &iterator, const Value &done)
{
Q_ASSERT(iterator.isObject());
Q_ASSERT(done.isBoolean());
@@ -978,7 +943,7 @@ ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value
return originalCompletion();
}
-ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, const Value &iterator)
+ReturnedValue Runtime::DestructureRestElement::call(ExecutionEngine *engine, const Value &iterator)
{
Q_ASSERT(iterator.isObject());
@@ -988,7 +953,7 @@ ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, co
uint index = 0;
while (1) {
ScopedValue n(scope);
- ScopedValue done(scope, method_iteratorNext(engine, iterator, n));
+ ScopedValue done(scope, IteratorNext::call(engine, iterator, n));
if (engine->hasException)
return Encode::undefined();
Q_ASSERT(done->isBoolean());
@@ -1000,7 +965,7 @@ ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, co
return array->asReturnedValue();
}
-void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, const Value &value)
+void Runtime::StoreNameSloppy::call(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1010,7 +975,7 @@ void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, con
engine->globalObject->put(name, value);
}
-void Runtime::method_storeNameStrict(ExecutionEngine *engine, int nameIndex, const Value &value)
+void Runtime::StoreNameStrict::call(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1021,7 +986,7 @@ void Runtime::method_storeNameStrict(ExecutionEngine *engine, int nameIndex, con
engine->throwReferenceError(name);
}
-ReturnedValue Runtime::method_loadProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
+ReturnedValue Runtime::LoadProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1041,7 +1006,7 @@ ReturnedValue Runtime::method_loadProperty(ExecutionEngine *engine, const Value
return o->get(name);
}
-ReturnedValue Runtime::method_loadName(ExecutionEngine *engine, int nameIndex)
+ReturnedValue Runtime::LoadName::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
@@ -1084,7 +1049,7 @@ static Object *getSuperBase(Scope &scope)
return proto;
}
-ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const Value &property)
+ReturnedValue Runtime::LoadSuperProperty::call(ExecutionEngine *engine, const Value &property)
{
Scope scope(engine);
Object *base = getSuperBase(scope);
@@ -1096,7 +1061,7 @@ ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const V
return base->get(key, &engine->currentStackFrame->jsFrame->thisObject);
}
-void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &property, const Value &value)
+void Runtime::StoreSuperProperty::call(ExecutionEngine *engine, const Value &property, const Value &value)
{
Scope scope(engine);
Object *base = getSuperBase(scope);
@@ -1110,7 +1075,40 @@ void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &pr
engine->throwTypeError();
}
-ReturnedValue Runtime::method_loadSuperConstructor(ExecutionEngine *engine, const Value &t)
+ReturnedValue Runtime::LoadGlobalLookup::call(ExecutionEngine *engine, Function *f, int index)
+{
+ Lookup *l = f->compilationUnit->runtimeLookups + index;
+ return l->globalGetter(l, engine);
+}
+
+ReturnedValue Runtime::LoadQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index)
+{
+ Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
+ return l->qmlContextPropertyGetter(l, engine, nullptr);
+}
+
+ReturnedValue Runtime::GetLookup::call(ExecutionEngine *engine, Function *f, const Value &base, int index)
+{
+ Lookup *l = f->compilationUnit->runtimeLookups + index;
+ return l->getter(l, engine, base);
+}
+
+void Runtime::SetLookupSloppy::call(Function *f, const Value &base, int index, const Value &value)
+{
+ ExecutionEngine *engine = f->internalClass->engine;
+ QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ l->setter(l, engine, const_cast<Value &>(base), value);
+}
+
+void Runtime::SetLookupStrict::call(Function *f, const Value &base, int index, const Value &value)
+{
+ ExecutionEngine *engine = f->internalClass->engine;
+ QV4::Lookup *l = f->compilationUnit->runtimeLookups + index;
+ if (!l->setter(l, engine, const_cast<Value &>(base), value))
+ engine->throwTypeError();
+}
+
+ReturnedValue Runtime::LoadSuperConstructor::call(ExecutionEngine *engine, const Value &t)
{
if (engine->currentStackFrame->thisObject() != Value::emptyValue().asReturnedValue()) {
return engine->throwReferenceError(QStringLiteral("super() already called."), QString(), 0, 0); // ### fix line number
@@ -1143,9 +1141,9 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y)
double dx = RuntimeHelpers::toNumber(x);
return dx == y.asDouble();
} else if (x.isBoolean()) {
- return Runtime::method_compareEqual(Value::fromDouble((double) x.booleanValue()), y);
+ return Runtime::CompareEqual::call(Value::fromDouble((double) x.booleanValue()), y);
} else if (y.isBoolean()) {
- return Runtime::method_compareEqual(x, Value::fromDouble((double) y.booleanValue()));
+ return Runtime::CompareEqual::call(x, Value::fromDouble((double) y.booleanValue()));
} else {
#ifdef V4_BOOTSTRAP
Q_UNIMPLEMENTED();
@@ -1155,11 +1153,11 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y)
if (yo && (x.isNumber() || x.isString())) {
Scope scope(yo->engine());
ScopedValue py(scope, RuntimeHelpers::objectDefaultValue(yo, PREFERREDTYPE_HINT));
- return Runtime::method_compareEqual(x, py);
+ return Runtime::CompareEqual::call(x, py);
} else if (xo && (y.isNumber() || y.isString())) {
Scope scope(xo->engine());
ScopedValue px(scope, RuntimeHelpers::objectDefaultValue(xo, PREFERREDTYPE_HINT));
- return Runtime::method_compareEqual(px, y);
+ return Runtime::CompareEqual::call(px, y);
}
#endif
}
@@ -1177,12 +1175,18 @@ Bool RuntimeHelpers::strictEqual(const Value &x, const Value &y)
if (x.isNumber())
return y.isNumber() && x.asDouble() == y.asDouble();
- if (x.isManaged())
+ if (x.isManaged()) {
+#ifdef V4_BOOTSTRAP
+ Q_UNIMPLEMENTED();
+ return false;
+#else
return y.isManaged() && x.cast<Managed>()->isEqualTo(y.cast<Managed>());
+#endif
+ }
return false;
}
-QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareGreaterThan::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1210,7 +1214,7 @@ QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareGreaterThan(pl, pr);
+ return Runtime::CompareGreaterThan::call(pl, pr);
#endif
}
@@ -1219,7 +1223,7 @@ QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r)
return dl > dr;
}
-QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareLessThan::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1247,7 +1251,7 @@ QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareLessThan(pl, pr);
+ return Runtime::CompareLessThan::call(pl, pr);
#endif
}
@@ -1256,7 +1260,7 @@ QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r)
return dl < dr;
}
-QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareGreaterEqual::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1284,7 +1288,7 @@ QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareGreaterEqual(pl, pr);
+ return Runtime::CompareGreaterEqual::call(pl, pr);
#endif
}
@@ -1293,7 +1297,7 @@ QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r)
return dl >= dr;
}
-QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r)
+QV4::Bool Runtime::CompareLessEqual::call(const Value &l, const Value &r)
{
TRACE2(l, r);
if (l.isInteger() && r.isInteger())
@@ -1321,7 +1325,7 @@ QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r)
QV4::Scope scope(e);
QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue());
QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue());
- return Runtime::method_compareLessEqual(pl, pr);
+ return Runtime::CompareLessEqual::call(pl, pr);
#endif
}
@@ -1331,21 +1335,21 @@ QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r)
}
#ifndef V4_BOOTSTRAP
-Bool Runtime::method_compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right)
+Bool Runtime::CompareInstanceof::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
TRACE2(left, right);
Scope scope(engine);
- ScopedValue v(scope, method_instanceof(engine, left, right));
+ ScopedValue v(scope, Instanceof::call(engine, left, right));
return v->booleanValue();
}
-uint Runtime::method_compareIn(ExecutionEngine *engine, const Value &left, const Value &right)
+uint Runtime::CompareIn::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
TRACE2(left, right);
Scope scope(engine);
- ScopedValue v(scope, method_in(engine, left, right));
+ ScopedValue v(scope, In::call(engine, left, right));
return v->booleanValue();
}
@@ -1359,7 +1363,7 @@ static ReturnedValue throwPropertyIsNotAFunctionTypeError(ExecutionEngine *engin
return engine->throwTypeError(msg);
}
-ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint index, Value argv[], int argc)
{
Scope scope(engine);
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
@@ -1372,7 +1376,8 @@ ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint ind
return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callQmlContextPropertyLookup(ExecutionEngine *engine, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index,
+ Value *argv, int argc)
{
Scope scope(engine);
ScopedValue thisObject(scope);
@@ -1385,7 +1390,7 @@ ReturnedValue Runtime::method_callQmlContextPropertyLookup(ExecutionEngine *engi
return static_cast<FunctionObject &>(function).call(thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Value *argv, int argc)
+ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Value *argv, int argc)
{
Scope scope(engine);
ScopedValue thisObject(scope);
@@ -1404,7 +1409,7 @@ ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Va
return function->call(thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, Value *argv, int argc)
+ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Value *argv, int argc)
{
Scope scope(engine);
ScopedValue thisObject(scope);
@@ -1422,8 +1427,9 @@ ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, V
return f->call(thisObject, argv, argc);
}
-ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)
+ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &baseRef, int nameIndex, Value *argv, int argc)
{
+ const Value *base = &baseRef;
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject lookupObject(scope, base);
@@ -1437,7 +1443,7 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base,
}
if (base->isManaged()) {
- Managed *m = static_cast<Managed *>(base);
+ const Managed *m = static_cast<const Managed *>(base);
lookupObject = m->internalClass()->prototype;
Q_ASSERT(m->internalClass()->prototype);
} else {
@@ -1461,20 +1467,21 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base,
return f->call(base, argv, argc);
}
-ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)
+ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc)
{
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
// ok to have the value on the stack here
- Value f = Value::fromReturnedValue(l->getter(l, engine, *base));
+ Value f = Value::fromReturnedValue(l->getter(l, engine, base));
if (!f.isFunctionObject())
return engine->throwTypeError();
- return static_cast<FunctionObject &>(f).call(base, argv, argc);
+ return static_cast<FunctionObject &>(f).call(&base, argv, argc);
}
-ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)
+ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &baseRef, const Value &index, Value *argv, int argc)
{
+ const Value *base = &baseRef;
Scope scope(engine);
ScopedValue thisObject(scope, base->toObject(engine));
base = thisObject;
@@ -1483,14 +1490,14 @@ ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base,
if (engine->hasException)
return Encode::undefined();
- ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str));
+ ScopedFunctionObject f(scope, static_cast<const Object *>(base)->get(str));
if (!f)
return engine->throwTypeError();
return f->call(base, argv, argc);
}
-ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
+ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
{
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
@@ -1498,11 +1505,12 @@ ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &fu
return static_cast<const FunctionObject &>(func).call(&undef, argv, argc);
}
-ReturnedValue Runtime::method_callWithReceiver(ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)
+ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Value &func,
+ const Value &thisObject, Value argv[], int argc)
{
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
- return static_cast<const FunctionObject &>(func).call(thisObject, argv, argc);
+ return static_cast<const FunctionObject &>(func).call(&thisObject, argv, argc);
}
struct CallArgs {
@@ -1528,11 +1536,11 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
}
// spread element
++i;
- it = Runtime::method_getIterator(scope.engine, argv[i], /* ForInIterator */ 1);
+ it = Runtime::GetIterator::call(scope.engine, argv[i], /* ForInIterator */ 1);
if (scope.engine->hasException)
return { nullptr, 0 };
while (1) {
- done = Runtime::method_iteratorNext(scope.engine, it, v);
+ done = Runtime::IteratorNext::call(scope.engine, it, v);
if (scope.engine->hasException)
return { nullptr, 0 };
Q_ASSERT(done->isBoolean());
@@ -1545,7 +1553,7 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
return { arguments, argCount };
}
-ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc)
+ReturnedValue Runtime::CallWithSpread::call(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc)
{
Q_ASSERT(argc >= 1);
if (!function.isFunctionObject())
@@ -1559,7 +1567,7 @@ ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Valu
return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc);
}
-ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
+ReturnedValue Runtime::Construct::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
{
if (!function.isFunctionObject())
return engine->throwTypeError();
@@ -1567,7 +1575,7 @@ ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &fu
return static_cast<const FunctionObject &>(function).callAsConstructor(argv, argc, &newTarget);
}
-ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
+ReturnedValue Runtime::ConstructWithSpread::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
{
if (!function.isFunctionObject())
return engine->throwTypeError();
@@ -1580,7 +1588,7 @@ ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const
return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget);
}
-ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *engine)
+ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *engine)
{
// IMPORTANT! The JIT assumes that this method has the same amount (or less) arguments than
// the jitted function, so it can safely do a tail call.
@@ -1610,13 +1618,13 @@ ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *en
return Encode::undefined();
}
-void Runtime::method_throwException(ExecutionEngine *engine, const Value &value)
+void Runtime::ThrowException::call(ExecutionEngine *engine, const Value &value)
{
if (!value.isEmpty())
engine->throwError(value);
}
-ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &value)
+ReturnedValue Runtime::TypeofValue::call(ExecutionEngine *engine, const Value &value)
{
Scope scope(engine);
ScopedString res(scope);
@@ -1647,83 +1655,109 @@ ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &
return res.asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameIndex)
+QV4::ReturnedValue Runtime::TypeofName::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedValue prop(scope, static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
- return method_typeofValue(engine, prop);
+ return TypeofValue::call(engine, prop);
}
-ReturnedValue Runtime::method_createWithContext(ExecutionEngine *engine, Value *jsStackFrame)
+void Runtime::PushCallContext::call(CppStackFrame *frame)
{
- QV4::Value &accumulator = jsStackFrame[CallData::Accumulator];
- accumulator = accumulator.toObject(engine);
- if (engine->hasException)
- return Encode::undefined();
- Q_ASSERT(accumulator.isObject());
- const Object &obj = static_cast<const Object &>(accumulator);
- ExecutionContext *context = static_cast<ExecutionContext *>(jsStackFrame + CallData::Context);
- return context->newWithContext(obj.d())->asReturnedValue();
+ frame->jsFrame->context = ExecutionContext::newCallContext(frame)->asReturnedValue();
}
-ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)
+ReturnedValue Runtime::PushWithContext::call(ExecutionEngine *engine, const Value &acc)
{
- ExecutionEngine *e = parent->engine();
- return parent->newCatchContext(e->currentStackFrame, blockIndex,
- e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex])->asReturnedValue();
+ CallData *jsFrame = engine->currentStackFrame->jsFrame;
+ Value &newAcc = jsFrame->accumulator;
+ newAcc = Value::fromHeapObject(acc.toObject(engine));
+ if (!engine->hasException) {
+ Q_ASSERT(newAcc.isObject());
+ const Object &obj = static_cast<const Object &>(newAcc);
+ Value &context = jsFrame->context;
+ auto ec = static_cast<const ExecutionContext *>(&context);
+ context = ec->newWithContext(obj.d())->asReturnedValue();
+ }
+ return newAcc.asReturnedValue();
}
-ReturnedValue Runtime::method_createBlockContext(ExecutionContext *parent, int index)
+void Runtime::PushCatchContext::call(ExecutionEngine *engine, int blockIndex, int exceptionVarNameIndex)
{
- ExecutionEngine *e = parent->engine();
- return parent->newBlockContext(e->currentStackFrame, index)->asReturnedValue();
+ auto name = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex];
+ engine->currentStackFrame->jsFrame->context = ExecutionContext::newCatchContext(engine->currentStackFrame, blockIndex, name)->asReturnedValue();
}
-ReturnedValue Runtime::method_cloneBlockContext(ExecutionContext *previous)
+void Runtime::PushBlockContext::call(ExecutionEngine *engine, int index)
{
- return ExecutionContext::cloneBlockContext(static_cast<Heap::CallContext *>(previous->d()))->asReturnedValue();
+ engine->currentStackFrame->jsFrame->context = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue();
}
+void Runtime::CloneBlockContext::call(ExecutionEngine *engine)
+{
+ auto frame = engine->currentStackFrame;
+ auto context = static_cast<Heap::CallContext *>(frame->jsFrame->context.m());
+ frame->jsFrame->context =
+ ExecutionContext::cloneBlockContext(engine, context)->asReturnedValue();
+}
-ReturnedValue Runtime::method_createScriptContext(ExecutionEngine *engine, int index)
+void Runtime::PushScriptContext::call(ExecutionEngine *engine, int index)
{
Q_ASSERT(engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_GlobalContext ||
engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_QmlContext);
ReturnedValue c = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue();
engine->setScriptContext(c);
- return c;
+ engine->currentStackFrame->jsFrame->context = c;
}
-ReturnedValue Runtime::method_popScriptContext(ExecutionEngine *engine)
+void Runtime::PopScriptContext::call(ExecutionEngine *engine)
{
ReturnedValue root = engine->rootContext()->asReturnedValue();
engine->setScriptContext(root);
- return root;
+ engine->currentStackFrame->jsFrame->context = root;
}
-void Runtime::method_throwReferenceError(ExecutionEngine *engine, int nameIndex)
+void Runtime::ThrowReferenceError::call(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
engine->throwReferenceError(name);
}
-void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
+void Runtime::ThrowOnNullOrUndefined::call(ExecutionEngine *engine, const Value &v)
+{
+ if (v.isNullOrUndefined())
+ engine->throwTypeError();
+}
+
+ReturnedValue Runtime::ConvertThisToObject::call(ExecutionEngine *engine, const Value &t)
+{
+ if (!t.isObject()) {
+ if (t.isNullOrUndefined()) {
+ return engine->globalObject->asReturnedValue();
+ } else {
+ return t.toObject(engine)->asReturnedValue();
+ }
+ }
+ return t.asReturnedValue();
+}
+
+void Runtime::DeclareVar::call(ExecutionEngine *engine, Bool deletable, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).createMutableBinding(name, deletable);
}
-ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
+ReturnedValue Runtime::ArrayLiteral::call(ExecutionEngine *engine, Value *values, uint length)
{
return engine->newArrayObject(values, length)->asReturnedValue();
}
-ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId, const QV4::Value *args, int argc)
+ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId, QV4::Value args[], int argc)
{
Scope scope(engine);
Scoped<InternalClass> klass(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]);
@@ -1796,7 +1830,8 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId
return o.asReturnedValue();
}
-ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classIndex, const Value &superClass, const Value *computedNames)
+ReturnedValue Runtime::CreateClass::call(ExecutionEngine *engine, int classIndex,
+ const Value &superClass, Value computedNames[])
{
const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit;
const QV4::CompiledData::Class *cls = unit->unitData()->classAt(classIndex);
@@ -1898,20 +1933,20 @@ ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classInde
return constructor->asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine)
+QV4::ReturnedValue Runtime::CreateMappedArgumentsObject::call(ExecutionEngine *engine)
{
Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext);
Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_ArgumentsObject);
return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine *engine)
+QV4::ReturnedValue Runtime::CreateUnmappedArgumentsObject::call(ExecutionEngine *engine)
{
Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_StrictArgumentsObject);
return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
}
-QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, int argIndex)
+QV4::ReturnedValue Runtime::CreateRestParameter::call(ExecutionEngine *engine, int argIndex)
{
const Value *values = engine->currentStackFrame->originalArguments + argIndex;
int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex;
@@ -1920,14 +1955,32 @@ QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine,
return engine->newArrayObject(values, nValues)->asReturnedValue();
}
-ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id)
+ReturnedValue Runtime::RegexpLiteral::call(ExecutionEngine *engine, int id)
{
Heap::RegExpObject *ro = engine->newRegExpObject(engine->currentStackFrame->v4Function->compilationUnit->runtimeRegularExpressions[id].as<RegExp>());
return ro->asReturnedValue();
}
+
+ReturnedValue Runtime::ToObject::call(ExecutionEngine *engine, const Value &obj)
+{
+ if (obj.isObject())
+ return obj.asReturnedValue();
+
+ return obj.toObject(engine)->asReturnedValue();
+}
+
+Bool Runtime::ToBoolean::call(const Value &obj)
+{
+ return obj.toBoolean();
+}
+
+ReturnedValue Runtime::ToNumber::call(ExecutionEngine *, const Value &v)
+{
+ return Encode(v.toNumber());
+}
#endif // V4_BOOTSTRAP
-ReturnedValue Runtime::method_uMinus(const Value &value)
+ReturnedValue Runtime::UMinus::call(const Value &value)
{
TRACE1(value);
@@ -1944,7 +1997,7 @@ ReturnedValue Runtime::method_uMinus(const Value &value)
// binary operators
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right)
+ReturnedValue Runtime::Add::call(ExecutionEngine *engine, const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1956,7 +2009,7 @@ ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, co
return RuntimeHelpers::addHelper(engine, left, right);
}
-ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
+ReturnedValue Runtime::Sub::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1969,7 +2022,7 @@ ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
return Value::fromDouble(lval - rval).asReturnedValue();
}
-ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
+ReturnedValue Runtime::Mul::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1982,7 +2035,7 @@ ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
return Value::fromDouble(lval * rval).asReturnedValue();
}
-ReturnedValue Runtime::method_div(const Value &left, const Value &right)
+ReturnedValue Runtime::Div::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2003,7 +2056,7 @@ ReturnedValue Runtime::method_div(const Value &left, const Value &right)
return Value::fromDouble(lval / rval).asReturnedValue();
}
-ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
+ReturnedValue Runtime::Mod::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2024,7 +2077,43 @@ ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
return Value::fromDouble(std::fmod(lval, rval)).asReturnedValue();
}
-ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
+ReturnedValue Runtime::Exp::call(const Value &base, const Value &exp)
+{
+ double b = base.toNumber();
+ double e = exp.toNumber();
+ if (qt_is_inf(e) && (b == 1 || b == -1))
+ return Encode(qt_snan());
+ return Encode(pow(b,e));
+}
+
+ReturnedValue Runtime::BitAnd::call(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode((int)(lval & rval));
+}
+
+ReturnedValue Runtime::BitOr::call(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode((int)(lval | rval));
+}
+
+ReturnedValue Runtime::BitXor::call(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode((int)(lval ^ rval));
+}
+
+ReturnedValue Runtime::Shl::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2033,7 +2122,7 @@ ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
return Encode((int)(lval << rval));
}
-ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
+ReturnedValue Runtime::Shr::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2042,7 +2131,7 @@ ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
return Encode((int)(lval >> rval));
}
-ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
+ReturnedValue Runtime::UShr::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2055,38 +2144,39 @@ ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
#endif // V4_BOOTSTRAP
-ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
+ReturnedValue Runtime::GreaterThan::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareGreaterThan(left, right);
+ bool r = CompareGreaterThan::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right)
+ReturnedValue Runtime::LessThan::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareLessThan(left, right);
+ bool r = CompareLessThan::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::GreaterEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareGreaterEqual(left, right);
+ bool r = CompareGreaterEqual::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::LessEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareLessEqual(left, right);
+ bool r = CompareLessEqual::call(left, right);
return Encode(r);
}
+#ifndef V4_BOOTSTRAP
struct LazyScope
{
ExecutionEngine *engine = nullptr;
@@ -2106,8 +2196,9 @@ struct LazyScope
**scopedValue = value;
}
};
+#endif
-Bool Runtime::method_compareEqual(const Value &left, const Value &right)
+Bool Runtime::CompareEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2216,23 +2307,23 @@ Bool Runtime::method_compareEqual(const Value &left, const Value &right)
}
}
-ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
+ReturnedValue Runtime::Equal::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = method_compareEqual(left, right);
+ bool r = CompareEqual::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::NotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- bool r = !method_compareEqual(left, right);
+ bool r = !CompareEqual::call(left, right);
return Encode(r);
}
-ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::StrictEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2240,7 +2331,7 @@ ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
return Encode(r);
}
-ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right)
+ReturnedValue Runtime::StrictNotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -2248,21 +2339,21 @@ ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &rig
return Encode(r);
}
-Bool Runtime::method_compareNotEqual(const Value &left, const Value &right)
+Bool Runtime::CompareNotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
- return !Runtime::method_compareEqual(left, right);
+ return !Runtime::CompareEqual::call(left, right);
}
-Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right)
+Bool Runtime::CompareStrictEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
return RuntimeHelpers::strictEqual(left, right);
}
-Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right)
+Bool Runtime::CompareStrictNotEqual::call(const Value &left, const Value &right)
{
TRACE2(left, right);
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 2be3ebf012..349099f8d5 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -52,8 +52,6 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4context_p.h"
-#include "qv4engine_p.h"
#include "qv4math_p.h"
#include "qv4runtimeapi_p.h"
#include <QtCore/qnumeric.h>
@@ -114,8 +112,6 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
static Bool strictEqual(const Value &x, const Value &y);
static ReturnedValue addHelper(ExecutionEngine *engine, const Value &left, const Value &right);
-
- static ReturnedValue getTemplateObject(Function *function, int index);
};
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index ceec13a3bb..13a73b7046 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -57,173 +57,442 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
typedef uint Bool;
-struct NoThrowEngine;
-namespace {
-template <typename T>
-struct ExceptionCheck {
- enum { NeedsCheck = 1 };
-};
-// push_catch and pop context methods shouldn't check for exceptions
-template <>
-struct ExceptionCheck<void (*)(QV4::NoThrowEngine *)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A>
-struct ExceptionCheck<void (*)(A, QV4::NoThrowEngine)> {
- enum { NeedsCheck = 0 };
-};
-template <>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A, typename B>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A, B)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A, typename B, typename C>
-struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
- enum { NeedsCheck = 0 };
-};
-} // anonymous namespace
-
-#define FOR_EACH_RUNTIME_METHOD(F) \
- /* call */ \
- F(ReturnedValue, callGlobalLookup, (ExecutionEngine *engine, uint index, Value *argv, int argc)) \
- F(ReturnedValue, callQmlContextPropertyLookup, (ExecutionEngine *engine, uint index, Value *argv, int argc)) \
- F(ReturnedValue, callName, (ExecutionEngine *engine, int nameIndex, Value *argv, int argc)) \
- F(ReturnedValue, callProperty, (ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)) \
- F(ReturnedValue, callPropertyLookup, (ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)) \
- F(ReturnedValue, callElement, (ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)) \
- F(ReturnedValue, callValue, (ExecutionEngine *engine, const Value &func, Value *argv, int argc)) \
- F(ReturnedValue, callWithReceiver, (ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)) \
- F(ReturnedValue, callPossiblyDirectEval, (ExecutionEngine *engine, Value *argv, int argc)) \
- F(ReturnedValue, callWithSpread, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \
- F(ReturnedValue, tailCall, (CppStackFrame *frame, ExecutionEngine *engine)) \
- \
- /* construct */ \
- F(ReturnedValue, construct, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \
- F(ReturnedValue, constructWithSpread, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \
- \
- /* load & store */ \
- F(void, storeNameStrict, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
- F(void, storeNameSloppy, (ExecutionEngine *engine, int nameIndex, const Value &value)) \
- F(void, storeProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \
- F(void, storeElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \
- F(void, storeElement_traced, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot)) \
- F(ReturnedValue, loadProperty, (ExecutionEngine *engine, const Value &object, int nameIndex)) \
- F(ReturnedValue, loadName, (ExecutionEngine *engine, int nameIndex)) \
- F(ReturnedValue, loadElement, (ExecutionEngine *engine, const Value &object, const Value &index)) \
- F(ReturnedValue, loadElement_traced, (ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot)) \
- F(ReturnedValue, loadSuperProperty, (ExecutionEngine *engine, const Value &property)) \
- F(void, storeSuperProperty, (ExecutionEngine *engine, const Value &property, const Value &value)) \
- F(ReturnedValue, loadSuperConstructor, (ExecutionEngine *engine, const Value &t)) \
- \
- /* typeof */ \
- F(ReturnedValue, typeofValue, (ExecutionEngine *engine, const Value &val)) \
- F(ReturnedValue, typeofName, (ExecutionEngine *engine, int nameIndex)) \
- \
- /* delete */ \
- F(bool, deleteProperty, (ExecutionEngine *engine, const Value &base, const Value &index)) \
- F(bool, deleteName, (ExecutionEngine *engine, int nameIndex)) \
- \
- /* exceptions & scopes */ \
- F(void, throwException, (ExecutionEngine *engine, const Value &value)) \
- F(ReturnedValue, createWithContext, (ExecutionEngine *, Value *jsStackFrame)) \
- F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)) \
- F(ReturnedValue, createBlockContext, (ExecutionContext *parent, int index)) \
- F(ReturnedValue, createScriptContext, (ExecutionEngine *engine, int index)) \
- F(ReturnedValue, cloneBlockContext, (ExecutionContext *previous)) \
- F(ReturnedValue, popScriptContext, (ExecutionEngine *engine)) \
- F(void, throwReferenceError, (ExecutionEngine *engine, int nameIndex)) \
- \
- /* closures */ \
- F(ReturnedValue, closure, (ExecutionEngine *engine, int functionId)) \
- \
- /* function header */ \
- F(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)) \
- F(ReturnedValue, createMappedArgumentsObject, (ExecutionEngine *engine)) \
- F(ReturnedValue, createUnmappedArgumentsObject, (ExecutionEngine *engine)) \
- F(ReturnedValue, createRestParameter, (ExecutionEngine *engine, int argIndex)) \
- \
- /* literals */ \
- F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \
- F(ReturnedValue, objectLiteral, (ExecutionEngine *engine, int classId, const Value *args, int argc)) \
- F(ReturnedValue, createClass, (ExecutionEngine *engine, int classIndex, const Value &heritage, const Value *computedNames)) \
- \
- /* for-in, for-of and array destructuring */ \
- F(ReturnedValue, getIterator, (ExecutionEngine *engine, const Value &in, int iterator)) \
- F(ReturnedValue, iteratorNext, (ExecutionEngine *engine, const Value &iterator, Value *value)) \
- F(ReturnedValue, iteratorNextForYieldStar, (ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)) \
- F(ReturnedValue, iteratorClose, (ExecutionEngine *engine, const Value &iterator, const Value &done)) \
- F(ReturnedValue, destructureRestElement, (ExecutionEngine *engine, const Value &iterator)) \
- \
- /* unary operators */ \
- F(ReturnedValue, uMinus, (const Value &value)) \
- \
- /* binary operators */ \
- F(ReturnedValue, instanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(ReturnedValue, in, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(ReturnedValue, add, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(ReturnedValue, sub, (const Value &left, const Value &right)) \
- F(ReturnedValue, mul, (const Value &left, const Value &right)) \
- F(ReturnedValue, div, (const Value &left, const Value &right)) \
- F(ReturnedValue, mod, (const Value &left, const Value &right)) \
- F(ReturnedValue, shl, (const Value &left, const Value &right)) \
- F(ReturnedValue, shr, (const Value &left, const Value &right)) \
- F(ReturnedValue, ushr, (const Value &left, const Value &right)) \
- F(ReturnedValue, greaterThan, (const Value &left, const Value &right)) \
- F(ReturnedValue, lessThan, (const Value &left, const Value &right)) \
- F(ReturnedValue, greaterEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, lessEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, equal, (const Value &left, const Value &right)) \
- F(ReturnedValue, notEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, strictEqual, (const Value &left, const Value &right)) \
- F(ReturnedValue, strictNotEqual, (const Value &left, const Value &right)) \
- \
- /* comparisons */ \
- F(Bool, compareGreaterThan, (const Value &l, const Value &r)) \
- F(Bool, compareLessThan, (const Value &l, const Value &r)) \
- F(Bool, compareGreaterEqual, (const Value &l, const Value &r)) \
- F(Bool, compareLessEqual, (const Value &l, const Value &r)) \
- F(Bool, compareEqual, (const Value &left, const Value &right)) \
- F(Bool, compareNotEqual, (const Value &left, const Value &right)) \
- F(Bool, compareStrictEqual, (const Value &left, const Value &right)) \
- F(Bool, compareStrictNotEqual, (const Value &left, const Value &right)) \
- \
- F(Bool, compareInstanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- F(Bool, compareIn, (ExecutionEngine *engine, const Value &left, const Value &right)) \
- \
- F(ReturnedValue, regexpLiteral, (ExecutionEngine *engine, int id))
struct Q_QML_PRIVATE_EXPORT Runtime {
- Runtime();
-
typedef ReturnedValue (*UnaryOperation)(const Value &value);
typedef ReturnedValue (*BinaryOperation)(const Value &left, const Value &right);
- typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *engine, const Value &left, const Value &right);
+ typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *, const Value &left, const Value &right);
-#define DEFINE_RUNTIME_METHOD_ENUM(returnvalue, name, args) name,
- enum RuntimeMethods {
- FOR_EACH_RUNTIME_METHOD(DEFINE_RUNTIME_METHOD_ENUM)
- RuntimeMethodCount,
- InvalidRuntimeMethod = RuntimeMethodCount
+ enum class Throws { No, Yes };
+ enum class ChangesContext { No, Yes };
+ enum class Pure { No, Yes };
+ enum class LastArgumentIsOutputValue { No, Yes };
+
+ template<Throws t, ChangesContext c = ChangesContext::No, Pure p = Pure::No,
+ LastArgumentIsOutputValue out = LastArgumentIsOutputValue::No>
+ struct Method
+ {
+ static constexpr bool throws = t == Throws::Yes;
+ static constexpr bool changesContext = c == ChangesContext::Yes;
+ static constexpr bool pure = p == Pure::Yes;
+ static constexpr bool lastArgumentIsOutputValue = out == LastArgumentIsOutputValue::Yes;
+ };
+ using PureMethod = Method<Throws::No, ChangesContext::No, Pure::Yes>;
+ using IteratorMethod = Method<Throws::Yes, ChangesContext::No, Pure::No,
+ LastArgumentIsOutputValue::Yes>;
+
+ /* call */
+ struct Q_QML_PRIVATE_EXPORT CallGlobalLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, uint, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallQmlContextPropertyLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, uint, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallName : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallPropertyLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, uint, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallElement : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallValue : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallWithReceiver : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallPossiblyDirectEval : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CallWithSpread : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT TailCall : Method<Throws::Yes>
+ {
+ static ReturnedValue call(CppStackFrame *, ExecutionEngine *);
};
-#undef DEFINE_RUNTIME_METHOD_ENUM
- void *runtimeMethods[RuntimeMethodCount];
+ /* construct */
+ struct Q_QML_PRIVATE_EXPORT Construct : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT ConstructWithSpread : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int);
+ };
- static uint runtimeMethodOffset(RuntimeMethods method) { return method*QT_POINTER_SIZE; }
+ /* load & store */
+ struct Q_QML_PRIVATE_EXPORT StoreNameStrict : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreNameSloppy : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreProperty : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreElement : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadName : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadElement : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadSuperProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StoreSuperProperty : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadSuperConstructor : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadGlobalLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT LoadQmlContextPropertyLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, uint);
+ };
+ struct Q_QML_PRIVATE_EXPORT GetLookup : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, const Value &, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT SetLookupStrict : Method<Throws::Yes>
+ {
+ static void call(Function *, const Value &, int, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT SetLookupSloppy : Method<Throws::Yes>
+ {
+ static void call(Function *, const Value &, int, const Value &);
+ };
+
+ /* typeof */
+ struct Q_QML_PRIVATE_EXPORT TypeofValue : PureMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT TypeofName : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+
+ /* delete */
+ struct Q_QML_PRIVATE_EXPORT DeleteProperty_NoThrow : Method<Throws::No>
+ {
+ static Bool call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeleteProperty : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeleteName_NoThrow : Method<Throws::No>
+ {
+ static Bool call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeleteName : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Function *, int);
+ };
+
+ /* exceptions & scopes */
+ struct Q_QML_PRIVATE_EXPORT ThrowException : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushCallContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(CppStackFrame *);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushWithContext : Method<Throws::Yes, ChangesContext::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushCatchContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *, int, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushBlockContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CloneBlockContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT PushScriptContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT PopScriptContext : Method<Throws::No, ChangesContext::Yes>
+ {
+ static void call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT ThrowReferenceError : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT ThrowOnNullOrUndefined : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, const Value &);
+ };
+
+ /* closures */
+ struct Q_QML_PRIVATE_EXPORT Closure : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
-#define RUNTIME_METHOD(returnvalue, name, args) \
- typedef returnvalue (*Method_##name)args; \
- enum { Method_##name##_NeedsExceptionCheck = ExceptionCheck<Method_##name>::NeedsCheck }; \
- static returnvalue method_##name args;
- FOR_EACH_RUNTIME_METHOD(RUNTIME_METHOD)
-#undef RUNTIME_METHOD
+ /* Function header */
+ struct Q_QML_PRIVATE_EXPORT ConvertThisToObject : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DeclareVar : Method<Throws::Yes>
+ {
+ static void call(ExecutionEngine *, Bool, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateMappedArgumentsObject : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateUnmappedArgumentsObject : Method<Throws::No>
+ {
+ static ReturnedValue call(ExecutionEngine *);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateRestParameter : PureMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+
+ /* literals */
+ struct Q_QML_PRIVATE_EXPORT ArrayLiteral : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, Value[], uint);
+ };
+ struct Q_QML_PRIVATE_EXPORT ObjectLiteral : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int, Value[], int);
+ };
+ struct Q_QML_PRIVATE_EXPORT CreateClass : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, int, const Value &, Value[]);
+ };
+
+ /* for-in, for-of and array destructuring */
+ struct Q_QML_PRIVATE_EXPORT GetIterator : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT IteratorNext : IteratorMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, Value *);
+ };
+ struct Q_QML_PRIVATE_EXPORT IteratorNextForYieldStar : IteratorMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value *);
+ };
+ struct Q_QML_PRIVATE_EXPORT IteratorClose : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT DestructureRestElement : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+
+ /* conversions */
+ struct Q_QML_PRIVATE_EXPORT ToObject : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT ToBoolean : PureMethod
+ {
+ static Bool call(const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT ToNumber : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &);
+ };
+ /* unary operators */
+ struct Q_QML_PRIVATE_EXPORT UMinus : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &);
+ };
+
+ /* binary operators */
+ struct Q_QML_PRIVATE_EXPORT Instanceof : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT In : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Add : Method<Throws::Yes>
+ {
+ static ReturnedValue call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Sub : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Mul : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Div : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Mod : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Exp : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT BitAnd : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT BitOr : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT BitXor : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Shl : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Shr : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT UShr : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT GreaterThan : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LessThan : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT GreaterEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT LessEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT Equal : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT NotEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StrictEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT StrictNotEqual : Method<Throws::Yes>
+ {
+ static ReturnedValue call(const Value &, const Value &);
+ };
+
+ /* comparisons */
+ struct Q_QML_PRIVATE_EXPORT CompareGreaterThan : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareLessThan : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareGreaterEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareLessEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareNotEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareStrictEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareStrictNotEqual : Method<Throws::Yes>
+ {
+ static Bool call(const Value &, const Value &);
+ };
+
+ struct Q_QML_PRIVATE_EXPORT CompareInstanceof : Method<Throws::Yes>
+ {
+ static Bool call(ExecutionEngine *, const Value &, const Value &);
+ };
+ struct Q_QML_PRIVATE_EXPORT CompareIn : Method<Throws::Yes>
+ {
+ static Bool call(ExecutionEngine *, const Value &, const Value &);
+ };
+
+ struct Q_QML_PRIVATE_EXPORT RegexpLiteral : PureMethod
+ {
+ static ReturnedValue call(ExecutionEngine *, int);
+ };
+ struct Q_QML_PRIVATE_EXPORT GetTemplateObject : PureMethod
+ {
+ static ReturnedValue call(Function *, int);
+ };
struct StackOffsets {
static const int tailCall_function = -1;
@@ -234,7 +503,6 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
};
static_assert(std::is_standard_layout<Runtime>::value, "Runtime needs to be standard layout in order for us to be able to use offsetof");
-static_assert(offsetof(Runtime, runtimeMethods) == 0, "JIT expects this to be the first member");
static_assert(sizeof(Runtime::BinaryOperation) == sizeof(void*), "JIT expects a function pointer to fit into a regular pointer, for cross-compilation offset translation");
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp
index 9866966936..99d0de5ec6 100644
--- a/src/qml/jsruntime/qv4runtimecodegen.cpp
+++ b/src/qml/jsruntime/qv4runtimecodegen.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qv4engine_p.h"
#include "qv4runtimecodegen_p.h"
#include "qv4compilerscanfunctions_p.h"
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index da71215bed..886dfaa521 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct SequencePrototype : public QV4::Object
+struct Q_QML_PRIVATE_EXPORT SequencePrototype : public QV4::Object
{
V4_PROTOTYPE(arrayPrototype)
void init();
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
deleted file mode 100644
index 50871a4d87..0000000000
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ /dev/null
@@ -1,427 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4serialize_p.h"
-
-#include <private/qv8engine_p.h>
-#if QT_CONFIG(qml_list_model)
-#include <private/qqmllistmodel_p.h>
-#include <private/qqmllistmodelworkeragent_p.h>
-#endif
-
-#include <private/qv4value_p.h>
-#include <private/qv4dateobject_p.h>
-#include <private/qv4regexpobject_p.h>
-#if QT_CONFIG(qml_sequence_object)
-#include <private/qv4sequenceobject_p.h>
-#endif
-#include <private/qv4objectproto_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-
-QT_BEGIN_NAMESPACE
-
-using namespace QV4;
-
-// We allow the following JavaScript types to be passed between the main and
-// the secondary thread:
-// + undefined
-// + null
-// + Boolean
-// + String
-// + Function
-// + Array
-// + "Simple" Objects
-// + Number
-// + Date
-// + RegExp
-// <quint8 type><quint24 size><data>
-
-enum Type {
- WorkerUndefined,
- WorkerNull,
- WorkerTrue,
- WorkerFalse,
- WorkerString,
- WorkerFunction,
- WorkerArray,
- WorkerObject,
- WorkerInt32,
- WorkerUint32,
- WorkerNumber,
- WorkerDate,
- WorkerRegexp,
-#if QT_CONFIG(qml_list_model)
- WorkerListModel,
-#endif
-#if QT_CONFIG(qml_sequence_object)
- WorkerSequence
-#endif
-};
-
-static inline quint32 valueheader(Type type, quint32 size = 0)
-{
- return quint8(type) << 24 | (size & 0xFFFFFF);
-}
-
-static inline Type headertype(quint32 header)
-{
- return (Type)(header >> 24);
-}
-
-static inline quint32 headersize(quint32 header)
-{
- return header & 0xFFFFFF;
-}
-
-static inline void push(QByteArray &data, quint32 value)
-{
- data.append((const char *)&value, sizeof(quint32));
-}
-
-static inline void push(QByteArray &data, double value)
-{
- data.append((const char *)&value, sizeof(double));
-}
-
-static inline void push(QByteArray &data, void *ptr)
-{
- data.append((const char *)&ptr, sizeof(void *));
-}
-
-static inline void reserve(QByteArray &data, int extra)
-{
- data.reserve(data.size() + extra);
-}
-
-static inline quint32 popUint32(const char *&data)
-{
- quint32 rv = *((const quint32 *)data);
- data += sizeof(quint32);
- return rv;
-}
-
-static inline double popDouble(const char *&data)
-{
- double rv = *((const double *)data);
- data += sizeof(double);
- return rv;
-}
-
-static inline void *popPtr(const char *&data)
-{
- void *rv = *((void *const *)data);
- data += sizeof(void *);
- return rv;
-}
-
-// XXX TODO: Check that worker script is exception safe in the case of
-// serialization/deserialization failures
-
-#define ALIGN(size) (((size) + 3) & ~3)
-void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine *engine)
-{
- QV4::Scope scope(engine);
-
- if (v.isEmpty()) {
- Q_ASSERT(!"Serialize: got empty value");
- } else if (v.isUndefined()) {
- push(data, valueheader(WorkerUndefined));
- } else if (v.isNull()) {
- push(data, valueheader(WorkerNull));
- } else if (v.isBoolean()) {
- push(data, valueheader(v.booleanValue() == true ? WorkerTrue : WorkerFalse));
- } else if (v.isString()) {
- const QString &qstr = v.toQString();
- int length = qstr.length();
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- int utf16size = ALIGN(length * sizeof(quint16));
-
- reserve(data, utf16size + sizeof(quint32));
- push(data, valueheader(WorkerString, length));
-
- int offset = data.size();
- data.resize(data.size() + utf16size);
- char *buffer = data.data() + offset;
-
- memcpy(buffer, qstr.constData(), length*sizeof(QChar));
- } else if (v.as<FunctionObject>()) {
- // XXX TODO: Implement passing function objects between the main and
- // worker scripts
- push(data, valueheader(WorkerUndefined));
- } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) {
- uint length = array->getLength();
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- reserve(data, sizeof(quint32) + length * sizeof(quint32));
- push(data, valueheader(WorkerArray, length));
- ScopedValue val(scope);
- for (uint ii = 0; ii < length; ++ii)
- serialize(data, (val = array->get(ii)), engine);
- } else if (v.isInteger()) {
- reserve(data, 2 * sizeof(quint32));
- push(data, valueheader(WorkerInt32));
- push(data, (quint32)v.integerValue());
-// } else if (v.IsUint32()) {
-// reserve(data, 2 * sizeof(quint32));
-// push(data, valueheader(WorkerUint32));
-// push(data, v.Uint32Value());
- } else if (v.isNumber()) {
- reserve(data, sizeof(quint32) + sizeof(double));
- push(data, valueheader(WorkerNumber));
- push(data, v.asDouble());
- } else if (const QV4::DateObject *d = v.as<DateObject>()) {
- reserve(data, sizeof(quint32) + sizeof(double));
- push(data, valueheader(WorkerDate));
- push(data, d->date());
- } else if (const RegExpObject *re = v.as<RegExpObject>()) {
- quint32 flags = re->flags();
- QString pattern = re->source();
- int length = pattern.length() + 1;
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- int utf16size = ALIGN(length * sizeof(quint16));
-
- reserve(data, sizeof(quint32) + utf16size);
- push(data, valueheader(WorkerRegexp, flags));
- push(data, (quint32)length);
-
- int offset = data.size();
- data.resize(data.size() + utf16size);
- char *buffer = data.data() + offset;
-
- memcpy(buffer, pattern.constData(), length*sizeof(QChar));
- } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
- // XXX TODO: Generalize passing objects between the main thread and worker scripts so
- // that others can trivially plug in their elements.
-#if QT_CONFIG(qml_list_model)
- QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
- if (lm && lm->agent()) {
- QQmlListModelWorkerAgent *agent = lm->agent();
- agent->addref();
- push(data, valueheader(WorkerListModel));
- push(data, (void *)agent);
- return;
- }
-#else
- Q_UNUSED(qobjectWrapper);
-#endif
- // No other QObject's are allowed to be sent
- push(data, valueheader(WorkerUndefined));
- } else if (const Object *o = v.as<Object>()) {
-#if QT_CONFIG(qml_sequence_object)
- if (o->isListType()) {
- // valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
- uint length = seqLength + 1;
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- reserve(data, sizeof(quint32) + length * sizeof(quint32));
- push(data, valueheader(WorkerSequence, length));
- serialize(data, QV4::Value::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
- ScopedValue val(scope);
- for (uint ii = 0; ii < seqLength; ++ii)
- serialize(data, (val = o->get(ii)), engine); // sequence elements
-
- return;
- }
-#endif
-
- // regular object
- QV4::ScopedValue val(scope, v);
- QV4::ScopedArrayObject properties(scope, QV4::ObjectPrototype::getOwnPropertyNames(engine, val));
- quint32 length = properties->getLength();
- if (length > 0xFFFFFF) {
- push(data, valueheader(WorkerUndefined));
- return;
- }
- push(data, valueheader(WorkerObject, length));
-
- QV4::ScopedValue s(scope);
- for (quint32 ii = 0; ii < length; ++ii) {
- s = properties->get(ii);
- serialize(data, s, engine);
-
- QV4::String *str = s->as<String>();
- val = o->get(str);
- if (scope.hasException())
- scope.engine->catchException();
-
- serialize(data, val, engine);
- }
- return;
- } else {
- push(data, valueheader(WorkerUndefined));
- }
-}
-
-ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
-{
- quint32 header = popUint32(data);
- Type type = headertype(header);
-
- Scope scope(engine);
-
- switch (type) {
- case WorkerUndefined:
- return QV4::Encode::undefined();
- case WorkerNull:
- return QV4::Encode::null();
- case WorkerTrue:
- return QV4::Encode(true);
- case WorkerFalse:
- return QV4::Encode(false);
- case WorkerString:
- {
- quint32 size = headersize(header);
- QString qstr((const QChar *)data, size);
- data += ALIGN(size * sizeof(quint16));
- return QV4::Encode(engine->newString(qstr));
- }
- case WorkerFunction:
- Q_ASSERT(!"Unreachable");
- break;
- case WorkerArray:
- {
- quint32 size = headersize(header);
- ScopedArrayObject a(scope, engine->newArrayObject());
- ScopedValue v(scope);
- for (quint32 ii = 0; ii < size; ++ii) {
- v = deserialize(data, engine);
- a->put(ii, v);
- }
- return a.asReturnedValue();
- }
- case WorkerObject:
- {
- quint32 size = headersize(header);
- ScopedObject o(scope, engine->newObject());
- ScopedValue name(scope);
- ScopedString n(scope);
- ScopedValue value(scope);
- for (quint32 ii = 0; ii < size; ++ii) {
- name = deserialize(data, engine);
- value = deserialize(data, engine);
- n = name->asReturnedValue();
- o->put(n, value);
- }
- return o.asReturnedValue();
- }
- case WorkerInt32:
- return QV4::Encode((qint32)popUint32(data));
- case WorkerUint32:
- return QV4::Encode(popUint32(data));
- case WorkerNumber:
- return QV4::Encode(popDouble(data));
- case WorkerDate:
- return QV4::Encode(engine->newDateObject(QV4::Value::fromDouble(popDouble(data))));
- case WorkerRegexp:
- {
- quint32 flags = headersize(header);
- quint32 length = popUint32(data);
- QString pattern = QString((const QChar *)data, length - 1);
- data += ALIGN(length * sizeof(quint16));
- return Encode(engine->newRegExpObject(pattern, flags));
- }
-#if QT_CONFIG(qml_list_model)
- case WorkerListModel:
- {
- void *ptr = popPtr(data);
- QQmlListModelWorkerAgent *agent = (QQmlListModelWorkerAgent *)ptr;
- QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(engine, agent));
- // ### Find a better solution then the ugly property
- QQmlListModelWorkerAgent::VariantRef ref(agent);
- QVariant var = qVariantFromValue(ref);
- QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
- QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
- rv->as<Object>()->defineReadonlyProperty(s, v);
-
- agent->release();
- agent->setEngine(engine);
- return rv->asReturnedValue();
- }
-#endif
-#if QT_CONFIG(qml_sequence_object)
- case WorkerSequence:
- {
- ScopedValue value(scope);
- bool succeeded = false;
- quint32 length = headersize(header);
- quint32 seqLength = length - 1;
- value = deserialize(data, engine);
- int sequenceType = value->integerValue();
- ScopedArrayObject array(scope, engine->newArrayObject());
- array->arrayReserve(seqLength);
- for (quint32 ii = 0; ii < seqLength; ++ii) {
- value = deserialize(data, engine);
- array->arrayPut(ii, value);
- }
- array->setArrayLengthUnchecked(seqLength);
- QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
- return QV4::SequencePrototype::fromVariant(engine, seqVariant, &succeeded);
- }
-#endif
- }
- Q_ASSERT(!"Unreachable");
- return QV4::Encode::undefined();
-}
-
-QByteArray Serialize::serialize(const QV4::Value &value, ExecutionEngine *engine)
-{
- QByteArray rv;
- serialize(rv, value, engine);
- return rv;
-}
-
-ReturnedValue Serialize::deserialize(const QByteArray &data, ExecutionEngine *engine)
-{
- const char *stream = data.constData();
- return deserialize(stream, engine);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/jsruntime/qv4setobject.cpp b/src/qml/jsruntime/qv4setobject.cpp
index 088ecbe30d..1664d1bd71 100644
--- a/src/qml/jsruntime/qv4setobject.cpp
+++ b/src/qml/jsruntime/qv4setobject.cpp
@@ -76,7 +76,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv,
ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("add")))));
if (!adder)
return scope.engine->throwTypeError();
- ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true));
+ ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true));
CHECK_EXCEPTION();
if (!iter)
return a.asReturnedValue();
@@ -84,7 +84,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv,
Value *nextValue = scope.alloc(1);
ScopedValue done(scope);
forever {
- done = Runtime::method_iteratorNext(scope.engine, iter, nextValue);
+ done = Runtime::IteratorNext::call(scope.engine, iter, nextValue);
CHECK_EXCEPTION();
if (done->toBoolean())
return a.asReturnedValue();
@@ -92,7 +92,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv,
adder->call(a, nextValue, 1);
if (scope.engine->hasException) {
ScopedValue falsey(scope, Encode(false));
- return Runtime::method_iteratorClose(scope.engine, iter, falsey);
+ return Runtime::IteratorClose::call(scope.engine, iter, falsey);
}
}
}
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h
index 44cfef9173..51a6acf43c 100644
--- a/src/qml/jsruntime/qv4stackframe_p.h
+++ b/src/qml/jsruntime/qv4stackframe_p.h
@@ -52,6 +52,7 @@
#include <private/qv4context_p.h>
#include <private/qv4enginebase_p.h>
+#include <private/qv4calldata_p.h>
#ifndef V4_BOOTSTRAP
#include <private/qv4function_p.h>
#endif
@@ -60,55 +61,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct CallData
-{
- enum Offsets {
- Function = 0,
- Context = 1,
- Accumulator = 2,
- This = 3,
- NewTarget = 4,
- Argc = 5,
-
- LastOffset = Argc,
- OffsetCount = LastOffset + 1
- };
-
- Value function;
- Value context;
- Value accumulator;
- Value thisObject;
- Value newTarget;
- Value _argc;
-
- int argc() const {
- Q_ASSERT(_argc.isInteger());
- return _argc.int_32();
- }
-
- void setArgc(int argc) {
- Q_ASSERT(argc >= 0);
- _argc.setInt_32(argc);
- }
-
- inline ReturnedValue argument(int i) const {
- return i < argc() ? args[i].asReturnedValue() : Value::undefinedValue().asReturnedValue();
- }
-
- Value args[1];
-
- static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); }
-};
-
-Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value);
-Q_STATIC_ASSERT(offsetof(CallData, function ) == CallData::Function * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, context ) == CallData::Context * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, accumulator) == CallData::Accumulator * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, thisObject ) == CallData::This * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, newTarget ) == CallData::NewTarget * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, _argc ) == CallData::Argc * sizeof(Value));
-Q_STATIC_ASSERT(offsetof(CallData, args ) == 6 * sizeof(Value));
-
struct Q_QML_EXPORT CppStackFrame {
EngineBase *engine;
Value *savedStackTop;
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 68d65f2e24..24a17bf5d5 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -256,8 +256,3 @@ qint64 String::virtualGetLength(const Managed *m)
}
#endif // V4_BOOTSTRAP
-
-uint String::toArrayIndex(const QString &str)
-{
- return QV4::String::toArrayIndex(str.constData(), str.constData() + str.length());
-}
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index fbd4f5f550..a986fe185e 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -54,6 +54,7 @@
#include "qv4managed_p.h"
#include <QtCore/private/qnumeric_p.h>
#include "qv4enginebase_p.h"
+#include "qv4stringtoarrayindex_p.h"
QT_BEGIN_NAMESPACE
@@ -242,40 +243,11 @@ protected:
#endif
public:
- static uint toArrayIndex(const QString &str);
-
-private:
- static inline uint toUInt(const QChar *ch) { return ch->unicode(); }
- static inline uint toUInt(const char *ch) { return static_cast<unsigned char>(*ch); }
-
- template <typename T>
- static inline uint toArrayIndex(const T *ch, const T *end)
- {
- uint i = toUInt(ch) - '0';
- if (i > 9)
- return UINT_MAX;
- ++ch;
- // reject "01", "001", ...
- if (i == 0 && ch != end)
- return UINT_MAX;
-
- while (ch < end) {
- uint x = toUInt(ch) - '0';
- if (x > 9)
- return UINT_MAX;
- if (mul_overflow(i, uint(10), &i) || add_overflow(i, x, &i)) // i = i * 10 + x
- return UINT_MAX;
- ++ch;
- }
- return i;
- }
-
-public:
template <typename T>
static inline uint calculateHashValue(const T *ch, const T* end, uint *subtype)
{
// array indices get their number as hash value
- uint h = toArrayIndex(ch, end);
+ uint h = stringToArrayIndex(ch, end);
if (h != UINT_MAX) {
if (subtype)
*subtype = Heap::StringOrSymbol::StringType_ArrayIndex;
@@ -283,12 +255,12 @@ public:
}
while (ch < end) {
- h = 31 * h + toUInt(ch);
+ h = 31 * h + charToUInt(ch);
++ch;
}
if (subtype)
- *subtype = (toUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
+ *subtype = (charToUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
return h;
}
};
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 6afa6d36d6..227df4014e 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -152,13 +152,14 @@ PropertyAttributes StringObject::virtualGetOwnProperty(const Managed *m, Propert
if (attributes != Attr_Invalid)
return attributes;
- const StringObject *s = static_cast<const StringObject *>(m);
- uint slen = s->d()->string->toQString().length();
- uint index = id.asArrayIndex();
- if (index < slen) {
- if (p)
- p->value = s->getIndex(index);
- return Attr_NotConfigurable|Attr_NotWritable;
+ if (id.isArrayIndex()) {
+ const uint index = id.asArrayIndex();
+ const auto s = static_cast<const StringObject *>(m);
+ if (index < uint(s->d()->string->toQString().length())) {
+ if (p)
+ p->value = s->getIndex(index);
+ return Attr_NotConfigurable|Attr_NotWritable;
+ }
}
return Object::virtualGetOwnProperty(m, id, p);
}
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4stringtoarrayindex_p.h
index c8700c3ca5..61bd988d1e 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4stringtoarrayindex_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QV4SERIALIZE_P_H
-#define QV4SERIALIZE_P_H
+#ifndef QV4STRINGTOARRAYINDEX_P_H
+#define QV4STRINGTOARRAYINDEX_P_H
//
// W A R N I N G
@@ -51,26 +51,46 @@
// We mean it.
//
-#include <QtCore/qbytearray.h>
-#include <private/qv4value_p.h>
+#include <QtCore/private/qnumeric_p.h>
+#include <QtCore/qstring.h>
+#include <limits>
QT_BEGIN_NAMESPACE
namespace QV4 {
-class Serialize {
-public:
+inline uint charToUInt(const QChar *ch) { return ch->unicode(); }
+inline uint charToUInt(const char *ch) { return static_cast<unsigned char>(*ch); }
- static QByteArray serialize(const Value &, ExecutionEngine *);
- static ReturnedValue deserialize(const QByteArray &, ExecutionEngine *);
+template <typename T>
+uint stringToArrayIndex(const T *ch, const T *end)
+{
+ uint i = charToUInt(ch) - '0';
+ if (i > 9)
+ return std::numeric_limits<uint>::max();
+ ++ch;
+ // reject "01", "001", ...
+ if (i == 0 && ch != end)
+ return std::numeric_limits<uint>::max();
-private:
- static void serialize(QByteArray &, const Value &, ExecutionEngine *);
- static ReturnedValue deserialize(const char *&, ExecutionEngine *);
-};
+ while (ch < end) {
+ uint x = charToUInt(ch) - '0';
+ if (x > 9)
+ return std::numeric_limits<uint>::max();
+ if (mul_overflow(i, uint(10), &i) || add_overflow(i, x, &i)) // i = i * 10 + x
+ return std::numeric_limits<uint>::max();
+ ++ch;
+ }
+ return i;
+}
+inline uint stringToArrayIndex(const QString &str)
+{
+ return stringToArrayIndex(str.constData(), str.constData() + str.length());
}
+} // namespace QV4
+
QT_END_NAMESPACE
-#endif // QV8WORKER_P_H
+#endif // QV4STRINGTOARRAYINDEX_P_H
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index faf7934c06..43e1dabb6d 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -459,24 +459,23 @@ Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type
ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ const bool isArrayIndex = id.isArrayIndex();
+ if (!isArrayIndex && !id.isCanonicalNumericIndexString())
return Object::virtualGet(m, id, receiver, hasProperty);
- // fall through, with index == UINT_MAX it'll do the right thing.
Scope scope(static_cast<const Object *>(m)->engine());
Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
if (a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- if (index >= a->length()) {
+ if (!isArrayIndex || id.asArrayIndex() >= a->length()) {
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
uint bytesPerElement = a->d()->type->bytesPerElement;
- uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
+ uint byteOffset = a->d()->byteOffset + id.asArrayIndex() * bytesPerElement;
Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
if (hasProperty)
@@ -486,27 +485,22 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ const bool isArrayIndex = id.isArrayIndex();
+ if (!isArrayIndex && !id.isCanonicalNumericIndexString())
return Object::virtualHasProperty(m, id);
- // fall through, with index == UINT_MAX it'll do the right thing.
const TypedArray *a = static_cast<const TypedArray *>(m);
if (a->d()->buffer->isDetachedBuffer()) {
a->engine()->throwTypeError();
return false;
}
- if (index >= a->length())
- return false;
- return true;
+ return isArrayIndex && id.asArrayIndex() < a->length();
}
PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ if (!id.isArrayIndex() && !id.isCanonicalNumericIndexString())
return Object::virtualGetOwnProperty(m, id, p);
- // fall through, with index == UINT_MAX it'll do the right thing.
bool hasProperty = false;
ReturnedValue v = virtualGet(m, id, m, &hasProperty);
@@ -517,10 +511,9 @@ PropertyAttributes TypedArray::virtualGetOwnProperty(const Managed *m, PropertyK
bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ const bool isArrayIndex = id.isArrayIndex();
+ if (!isArrayIndex && !id.isCanonicalNumericIndexString())
return Object::virtualPut(m, id, value, receiver);
- // fall through, with index == UINT_MAX it'll do the right thing.
ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
if (v4->hasException)
@@ -531,6 +524,10 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
if (a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
+ if (!isArrayIndex)
+ return false;
+
+ const uint index = id.asArrayIndex();
if (index >= a->length())
return false;
@@ -547,11 +544,12 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
{
- uint index = id.asArrayIndex();
- if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
- return Object::virtualDefineOwnProperty(m, id, p, attrs);
- // fall through, with index == UINT_MAX it'll do the right thing.
+ if (!id.isArrayIndex()) {
+ return !id.isCanonicalNumericIndexString()
+ && Object::virtualDefineOwnProperty(m, id, p, attrs);
+ }
+ const uint index = id.asArrayIndex();
TypedArray *a = static_cast<TypedArray *>(m);
if (index >= a->length() || attrs.isAccessor())
return false;
@@ -1595,7 +1593,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_toLocaleString(const Function
R += separator;
v = instance->get(k);
- v = Runtime::method_callElement(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
+ v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0);
s = v->toString(scope.engine);
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index cbc153bb86..82cf11f148 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -36,11 +36,11 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include <qv4engine_p.h>
+
#include <qv4runtime_p.h>
-#include <qv4string_p.h>
#include <qv4propertykey_p.h>
#ifndef V4_BOOTSTRAP
+#include <qv4string_p.h>
#include <qv4symbol_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
@@ -248,7 +248,6 @@ QV4::PropertyKey Value::toPropertyKey(ExecutionEngine *e) const
ScopedStringOrSymbol s(scope, v);
return s->toPropertyKey();
}
-#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
if (_val == other._val)
@@ -285,7 +284,6 @@ bool Value::sameValueZero(Value other) const {
return false;
}
-#ifndef V4_BOOTSTRAP
Heap::String *Value::toString(ExecutionEngine *e, Value val)
{
return RuntimeHelpers::convertToString(e, val);
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index b4a045edfb..da08841026 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -281,8 +281,22 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool isUndefined() const { return _val == 0; }
inline bool isDouble() const { return (_val >> IsDouble_Shift); }
- inline bool isManaged() const { return _val && ((_val >> IsManagedOrUndefined_Shift) == 0); }
- inline bool isManagedOrUndefined() const { return ((_val >> IsManagedOrUndefined_Shift) == 0); }
+ inline bool isManaged() const
+ {
+#if QT_POINTER_SIZE == 4
+ return value() && tag() == Managed_Type_Internal;
+#else
+ return _val && ((_val >> IsManagedOrUndefined_Shift) == 0);
+#endif
+ }
+ inline bool isManagedOrUndefined() const
+ {
+#if QT_POINTER_SIZE == 4
+ return tag() == Managed_Type_Internal;
+#else
+ return ((_val >> IsManagedOrUndefined_Shift) == 0);
+#endif
+ }
inline bool isIntOrBool() const {
return (_val >> IsIntegerOrBool_Shift) == 3;
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index e4d8bcaafc..e117e509ab 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -41,7 +41,6 @@
#include "qv4functionobject_p.h"
#include "qv4objectproto_p.h"
#include <private/qqmlvaluetypewrapper_p.h>
-#include <private/qv8engine_p.h>
#include <private/qv4qobjectwrapper_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index d2c91da12c..d348a79861 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -61,12 +61,16 @@
#include "qv4alloca_p.h"
+#if QT_CONFIG(qml_jit)
#include <private/qv4baselinejit_p.h>
+#endif
#include <qtqml_tracepoints_p.h>
#undef COUNT_INSTRUCTIONS
+enum { ShowWhenDeoptimiationHappens = 0 };
+
extern "C" {
// This is the interface to Qt Creator's (new) QML debugger.
@@ -345,73 +349,9 @@ static struct InstrCount {
#undef CHECK_EXCEPTION
#endif
#define CHECK_EXCEPTION \
- if (engine->hasException) \
+ if (engine->hasException || engine->isInterrupted) \
goto handleUnwind
-static inline void traceJumpTakesTruePath(bool truePathTaken, Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- *traceInfo |= truePathTaken ? quint8(ObservedTraceValues::TruePathTaken)
- : quint8(ObservedTraceValues::FalsePathTaken);
-#else
- Q_UNUSED(truePathTaken);
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
-static inline void traceValue(ReturnedValue acc, Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- switch (Primitive::fromReturnedValue(acc).type()) {
- case QV4::Value::Integer_Type:
- *traceInfo |= quint8(ObservedTraceValues::Integer);
- break;
- case QV4::Value::Boolean_Type:
- *traceInfo |= quint8(ObservedTraceValues::Boolean);
- break;
- case QV4::Value::Double_Type:
- *traceInfo |= quint8(ObservedTraceValues::Double);
- break;
- default:
- *traceInfo |= quint8(ObservedTraceValues::Other);
- break;
- }
-#else
- Q_UNUSED(acc);
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
-static inline void traceDoubleValue(Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- *traceInfo |= quint8(ObservedTraceValues::Double);
-#else
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
-static inline void traceOtherValue(Function *f, int slot)
-{
-#if QT_CONFIG(qml_tracing)
- quint8 *traceInfo = f->traceInfo(slot);
- Q_ASSERT(traceInfo);
- *traceInfo |= quint8(ObservedTraceValues::Other);
-#else
- Q_UNUSED(f);
- Q_UNUSED(slot);
-#endif
-}
-
static inline Heap::CallContext *getScope(QV4::Value *stack, int level)
{
Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(stack[CallData::Context]).d();
@@ -491,7 +431,7 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
QV4::Debugging::Debugger *debugger = engine->debugger();
-#ifdef V4_ENABLE_JIT
+#if QT_CONFIG(qml_jit)
if (debugger == nullptr) {
if (function->jittedCode == nullptr) {
if (engine->canJIT(function))
@@ -499,16 +439,20 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
else
++function->interpreterCallCount;
}
- if (function->jittedCode != nullptr)
- return function->jittedCode(frame, engine);
}
-#endif // V4_ENABLE_JIT
+#endif // QT_CONFIG(qml_jit)
// interpreter
if (debugger)
debugger->enteringFunction();
- ReturnedValue result = interpret(frame, engine, function->codeData);
+ ReturnedValue result;
+ if (function->jittedCode != nullptr && debugger == nullptr) {
+ result = function->jittedCode(frame, engine);
+ } else {
+ // interpreter
+ result = interpret(frame, engine, function->codeData);
+ }
if (debugger)
debugger->leavingFunction(result);
@@ -523,11 +467,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
QV4::ReturnedValue acc = accumulator.asReturnedValue();
Value *stack = reinterpret_cast<Value *>(frame->jsFrame);
- if (function->tracingEnabled()) {
- for (int i = 0; i < int(function->nFormals); ++i)
- traceValue(frame->jsFrame->argument(i), function, i);
- }
-
MOTH_JUMP_TABLE;
for (;;) {
@@ -586,7 +525,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
Q_ASSERT(cc->type != QV4::Heap::CallContext::Type_GlobalContext);
acc = cc->locals[index].asReturnedValue();
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadLocal)
MOTH_BEGIN_INSTR(StoreLocal)
@@ -599,7 +537,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(LoadScopedLocal)
auto cc = getScope(stack, scope);
acc = cc->locals[index].asReturnedValue();
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadScopedLocal)
MOTH_BEGIN_INSTR(StoreScopedLocal)
@@ -613,18 +550,17 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(LoadRuntimeString)
MOTH_BEGIN_INSTR(MoveRegExp)
- STACK_VALUE(destReg) = Runtime::method_regexpLiteral(engine, regExpId);
+ STACK_VALUE(destReg) = Runtime::RegexpLiteral::call(engine, regExpId);
MOTH_END_INSTR(MoveRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
- acc = Runtime::method_closure(engine, value);
+ acc = Runtime::Closure::call(engine, value);
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
STORE_IP();
- acc = Runtime::method_loadName(engine, name);
+ acc = Runtime::LoadName::call(engine, name);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(LoadGlobalLookup)
@@ -632,7 +568,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
acc = l->globalGetter(l, engine);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadGlobalLookup)
MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup)
@@ -640,54 +575,41 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
QV4::Lookup *l = function->compilationUnit->runtimeLookups + index;
acc = l->qmlContextPropertyGetter(l, engine, nullptr);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadQmlContextPropertyLookup)
MOTH_BEGIN_INSTR(StoreNameStrict)
STORE_IP();
STORE_ACC();
- Runtime::method_storeNameStrict(engine, name, accumulator);
+ Runtime::StoreNameStrict::call(engine, name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreNameStrict)
MOTH_BEGIN_INSTR(StoreNameSloppy)
STORE_IP();
STORE_ACC();
- Runtime::method_storeNameSloppy(engine, name, accumulator);
+ Runtime::StoreNameSloppy::call(engine, name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreNameSloppy)
MOTH_BEGIN_INSTR(LoadElement)
STORE_IP();
STORE_ACC();
-#if QT_CONFIG(qml_tracing)
- acc = Runtime::method_loadElement_traced(engine, STACK_VALUE(base), accumulator, function->traceInfo(traceSlot));
- traceValue(acc, function, traceSlot);
-#else
- Q_UNUSED(traceSlot);
- acc = Runtime::method_loadElement(engine, STACK_VALUE(base), accumulator);
-#endif
+ acc = Runtime::LoadElement::call(engine, STACK_VALUE(base), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
STORE_IP();
STORE_ACC();
-#if QT_CONFIG(qml_tracing)
- Runtime::method_storeElement_traced(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator, function->traceInfo(traceSlot));
-#else
- Q_UNUSED(traceSlot);
- Runtime::method_storeElement(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator);
-#endif
+ Runtime::StoreElement::call(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_loadProperty(engine, accumulator, name);
+ acc = Runtime::LoadProperty::call(engine, accumulator, name);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
@@ -706,13 +628,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = l->getter(l, engine, accumulator);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
STORE_IP();
STORE_ACC();
- Runtime::method_storeProperty(engine, STACK_VALUE(base), name, accumulator);
+ Runtime::StoreProperty::call(engine, STACK_VALUE(base), name, accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
@@ -728,14 +649,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(LoadSuperProperty)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_loadSuperProperty(engine, STACK_VALUE(property));
+ acc = Runtime::LoadSuperProperty::call(engine, STACK_VALUE(property));
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadSuperProperty)
MOTH_BEGIN_INSTR(StoreSuperProperty)
STORE_IP();
STORE_ACC();
- Runtime::method_storeSuperProperty(engine, STACK_VALUE(property), accumulator);
+ Runtime::StoreSuperProperty::call(engine, STACK_VALUE(property), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreSuperProperty)
@@ -766,7 +687,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(IteratorNextForYieldStar)
STORE_ACC();
- acc = Runtime::method_iteratorNextForYieldStar(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object));
+ acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object));
CHECK_EXCEPTION;
MOTH_END_INSTR(IteratorNextForYieldStar)
@@ -780,7 +701,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
Value undef = Value::undefinedValue();
acc = static_cast<const FunctionObject &>(func).call(&undef, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallWithReceiver)
@@ -792,14 +712,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
}
acc = static_cast<const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallWithReceiver)
MOTH_BEGIN_INSTR(CallProperty)
STORE_IP();
- acc = Runtime::method_callProperty(engine, stack + base, name, stack + argv, argc);
+ acc = Runtime::CallProperty::call(engine, stack[base], name, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
@@ -827,49 +745,42 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
STORE_IP();
- acc = Runtime::method_callElement(engine, stack + base, STACK_VALUE(index), stack + argv, argc);
+ acc = Runtime::CallElement::call(engine, stack[base], STACK_VALUE(index), stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallName)
STORE_IP();
- acc = Runtime::method_callName(engine, name, stack + argv, argc);
+ acc = Runtime::CallName::call(engine, name, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallName)
MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
STORE_IP();
- acc = Runtime::method_callPossiblyDirectEval(engine, stack + argv, argc);
+ acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallPossiblyDirectEval)
MOTH_BEGIN_INSTR(CallGlobalLookup)
STORE_IP();
- acc = Runtime::method_callGlobalLookup(engine, index, stack + argv, argc);
+ acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup)
STORE_IP();
- acc = Runtime::method_callQmlContextPropertyLookup(engine, index, stack + argv, argc);
+ acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallQmlContextPropertyLookup)
MOTH_BEGIN_INSTR(CallWithSpread)
STORE_IP();
- acc = Runtime::method_callWithSpread(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc);
+ acc = Runtime::CallWithSpread::call(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(CallWithSpread)
MOTH_BEGIN_INSTR(TailCall)
@@ -878,19 +789,19 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
*engine->jsAlloca(1) = Primitive::fromInt32(argv);
*engine->jsAlloca(1) = STACK_VALUE(thisObject);
*engine->jsAlloca(1) = STACK_VALUE(func);
- return Runtime::method_tailCall(frame, engine);
+ return Runtime::TailCall::call(frame, engine);
CHECK_EXCEPTION;
MOTH_END_INSTR(TailCall)
MOTH_BEGIN_INSTR(Construct)
STORE_IP();
- acc = Runtime::method_construct(engine, STACK_VALUE(func), ACC, stack + argv, argc);
+ acc = Runtime::Construct::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(Construct)
MOTH_BEGIN_INSTR(ConstructWithSpread)
STORE_IP();
- acc = Runtime::method_constructWithSpread(engine, STACK_VALUE(func), ACC, stack + argv, argc);
+ acc = Runtime::ConstructWithSpread::call(engine, STACK_VALUE(func), ACC, stack + argv, argc);
CHECK_EXCEPTION;
MOTH_END_INSTR(ConstructWithSpread)
@@ -918,7 +829,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
if (ACC.isEmpty()) {
STORE_IP();
STORE_ACC();
- Runtime::method_throwReferenceError(engine, name);
+ Runtime::ThrowReferenceError::call(engine, name);
goto handleUnwind;
}
MOTH_END_INSTR(DeadTemporalZoneCheck)
@@ -926,7 +837,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(ThrowException)
STORE_IP();
STORE_ACC();
- Runtime::method_throwException(engine, accumulator);
+ Runtime::ThrowException::call(engine, accumulator);
goto handleUnwind;
MOTH_END_INSTR(ThrowException)
@@ -944,40 +855,36 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(SetException)
MOTH_BEGIN_INSTR(PushCatchContext)
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, index, name);
+ Runtime::PushCatchContext::call(engine, index, name);
MOTH_END_INSTR(PushCatchContext)
MOTH_BEGIN_INSTR(CreateCallContext)
- stack[CallData::Context] = ExecutionContext::newCallContext(frame);
+ Runtime::PushCallContext::call(frame);
MOTH_END_INSTR(CreateCallContext)
MOTH_BEGIN_INSTR(PushWithContext)
STORE_IP();
STORE_ACC();
- auto ctx = Runtime::method_createWithContext(engine, stack);
+ acc = Runtime::PushWithContext::call(engine, stack[CallData::Accumulator]);
CHECK_EXCEPTION;
- STACK_VALUE(CallData::Context) = ctx;
MOTH_END_INSTR(PushWithContext)
MOTH_BEGIN_INSTR(PushBlockContext)
STORE_ACC();
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_createBlockContext(c, index);
+ Runtime::PushBlockContext::call(engine, index);
MOTH_END_INSTR(PushBlockContext)
MOTH_BEGIN_INSTR(CloneBlockContext)
STORE_ACC();
- ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
- STACK_VALUE(CallData::Context) = Runtime::method_cloneBlockContext(c);
+ Runtime::CloneBlockContext::call(engine);
MOTH_END_INSTR(CloneBlockContext)
MOTH_BEGIN_INSTR(PushScriptContext)
- STACK_VALUE(CallData::Context) = Runtime::method_createScriptContext(engine, index);
+ Runtime::PushScriptContext::call(engine, index);
MOTH_END_INSTR(PushScriptContext)
MOTH_BEGIN_INSTR(PopScriptContext)
- STACK_VALUE(CallData::Context) = Runtime::method_popScriptContext(engine);
+ Runtime::PopScriptContext::call(engine);
MOTH_END_INSTR(PopScriptContext)
MOTH_BEGIN_INSTR(PopContext)
@@ -988,14 +895,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(GetIterator)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_getIterator(engine, accumulator, iterator);
+ acc = Runtime::GetIterator::call(engine, accumulator, iterator);
CHECK_EXCEPTION;
MOTH_END_INSTR(GetIterator)
MOTH_BEGIN_INSTR(IteratorNext)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_iteratorNext(engine, accumulator, &STACK_VALUE(value));
+ acc = Runtime::IteratorNext::call(engine, accumulator, &STACK_VALUE(value));
STACK_VALUE(done) = acc;
CHECK_EXCEPTION;
MOTH_END_INSTR(IteratorNext)
@@ -1003,97 +910,73 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(IteratorClose)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_iteratorClose(engine, accumulator, STACK_VALUE(done));
+ acc = Runtime::IteratorClose::call(engine, accumulator, STACK_VALUE(done));
CHECK_EXCEPTION;
MOTH_END_INSTR(IteratorClose)
MOTH_BEGIN_INSTR(DestructureRestElement)
STORE_IP();
STORE_ACC();
- acc = Runtime::method_destructureRestElement(engine, ACC);
+ acc = Runtime::DestructureRestElement::call(engine, ACC);
CHECK_EXCEPTION;
MOTH_END_INSTR(DestructureRestElement)
MOTH_BEGIN_INSTR(DeleteProperty)
- if (!Runtime::method_deleteProperty(engine, STACK_VALUE(base), STACK_VALUE(index))) {
- if (function->isStrict()) {
- STORE_IP();
- engine->throwTypeError();
- goto handleUnwind;
- }
- acc = Encode(false);
- } else {
- acc = Encode(true);
- }
+ acc = Runtime::DeleteProperty::call(engine, function, STACK_VALUE(base), STACK_VALUE(index));
+ CHECK_EXCEPTION;
MOTH_END_INSTR(DeleteProperty)
MOTH_BEGIN_INSTR(DeleteName)
- if (!Runtime::method_deleteName(engine, name)) {
- if (function->isStrict()) {
- STORE_IP();
- QString n = function->compilationUnit->runtimeStrings[name]->toQString();
- engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(n));
- goto handleUnwind;
- }
- acc = Encode(false);
- } else {
- acc = Encode(true);
- }
+ acc = Runtime::DeleteName::call(engine, function, name);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(DeleteName)
MOTH_BEGIN_INSTR(TypeofName)
- acc = Runtime::method_typeofName(engine, name);
+ acc = Runtime::TypeofName::call(engine, name);
MOTH_END_INSTR(TypeofName)
MOTH_BEGIN_INSTR(TypeofValue)
STORE_ACC();
- acc = Runtime::method_typeofValue(engine, accumulator);
+ acc = Runtime::TypeofValue::call(engine, accumulator);
MOTH_END_INSTR(TypeofValue)
MOTH_BEGIN_INSTR(DeclareVar)
- Runtime::method_declareVar(engine, isDeletable, varName);
+ Runtime::DeclareVar::call(engine, isDeletable, varName);
MOTH_END_INSTR(DeclareVar)
MOTH_BEGIN_INSTR(DefineArray)
QV4::Value *arguments = stack + args;
- acc = Runtime::method_arrayLiteral(engine, arguments, argc);
+ acc = Runtime::ArrayLiteral::call(engine, arguments, argc);
MOTH_END_INSTR(DefineArray)
MOTH_BEGIN_INSTR(DefineObjectLiteral)
QV4::Value *arguments = stack + args;
- acc = Runtime::method_objectLiteral(engine, internalClassId, arguments, argc);
+ acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc);
MOTH_END_INSTR(DefineObjectLiteral)
MOTH_BEGIN_INSTR(CreateClass)
- acc = Runtime::method_createClass(engine, classIndex, STACK_VALUE(heritage), stack + computedNames);
+ acc = Runtime::CreateClass::call(engine, classIndex, STACK_VALUE(heritage), stack + computedNames);
MOTH_END_INSTR(CreateClass)
MOTH_BEGIN_INSTR(CreateMappedArgumentsObject)
- acc = Runtime::method_createMappedArgumentsObject(engine);
+ acc = Runtime::CreateMappedArgumentsObject::call(engine);
MOTH_END_INSTR(CreateMappedArgumentsObject)
MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
- acc = Runtime::method_createUnmappedArgumentsObject(engine);
+ acc = Runtime::CreateUnmappedArgumentsObject::call(engine);
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
MOTH_BEGIN_INSTR(CreateRestParameter)
- acc = Runtime::method_createRestParameter(engine, argIndex);
+ acc = Runtime::CreateRestParameter::call(engine, argIndex);
MOTH_END_INSTR(CreateRestParameter)
MOTH_BEGIN_INSTR(ConvertThisToObject)
- Value *t = &stack[CallData::This];
- if (!t->isObject()) {
- if (t->isNullOrUndefined()) {
- *t = engine->globalObject->asReturnedValue();
- } else {
- *t = t->toObject(engine)->asReturnedValue();
- CHECK_EXCEPTION;
- }
- }
+ stack[CallData::This] = Runtime::ConvertThisToObject::call(engine, stack[CallData::This]);
+ CHECK_EXCEPTION;
MOTH_END_INSTR(ConvertThisToObject)
MOTH_BEGIN_INSTR(LoadSuperConstructor)
- acc = Runtime::method_loadSuperConstructor(engine, stack[CallData::Function]);
+ acc = Runtime::LoadSuperConstructor::call(engine, stack[CallData::Function]);
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadSuperConstructor)
@@ -1112,7 +995,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
takeJump = ACC.int_32();
else
takeJump = ACC.toBoolean();
- traceJumpTakesTruePath(takeJump, function, traceSlot);
if (takeJump)
code += offset;
MOTH_END_INSTR(JumpTrue)
@@ -1123,7 +1005,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
takeJump = !ACC.int_32();
else
takeJump = !ACC.toBoolean();
- traceJumpTakesTruePath(!takeJump, function, traceSlot);
if (takeJump)
code += offset;
MOTH_END_INSTR(JumpFalse)
@@ -1138,6 +1019,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
code += offset;
MOTH_END_INSTR(JumpNotUndefined)
+ MOTH_BEGIN_INSTR(CheckException)
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CheckException)
+
MOTH_BEGIN_INSTR(CmpEqNull)
acc = Encode(ACC.isNullOrUndefined());
MOTH_END_INSTR(CmpEqNull)
@@ -1174,7 +1059,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.int_32() == ACC.int_32());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareEqual(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpEq)
@@ -1185,7 +1070,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(bool(left.int_32() != ACC.int_32()));
} else {
STORE_ACC();
- acc = Encode(bool(!Runtime::method_compareEqual(left, accumulator)));
+ acc = Encode(bool(!Runtime::CompareEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpNe)
@@ -1198,7 +1083,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() > ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareGreaterThan(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareGreaterThan::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpGt)
@@ -1211,7 +1096,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() >= ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareGreaterEqual(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareGreaterEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpGe)
@@ -1224,7 +1109,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() < ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareLessThan(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareLessThan::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpLt)
@@ -1237,7 +1122,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(left.asDouble() <= ACC.asDouble());
} else {
STORE_ACC();
- acc = Encode(bool(Runtime::method_compareLessEqual(left, accumulator)));
+ acc = Encode(bool(Runtime::CompareLessEqual::call(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpLe)
@@ -1247,7 +1132,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
acc = Encode(true);
} else {
STORE_ACC();
- acc = Encode(bool(RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator)));
+ acc = Runtime::StrictEqual::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpStrictEqual)
@@ -1255,7 +1140,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(CmpStrictNotEqual)
if (STACK_VALUE(lhs).rawValue() != ACC.rawValue() || ACC.isNaN()) {
STORE_ACC();
- acc = Encode(!RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator));
+ acc = Runtime::StrictNotEqual::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
} else {
acc = Encode(false);
@@ -1264,13 +1149,13 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(CmpIn)
STORE_ACC();
- acc = Runtime::method_in(engine, STACK_VALUE(lhs), accumulator);
+ acc = Runtime::In::call(engine, STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpIn)
MOTH_BEGIN_INSTR(CmpInstanceOf)
STORE_ACC();
- acc = Runtime::method_instanceof(engine, STACK_VALUE(lhs), ACC);
+ acc = Runtime::Instanceof::call(engine, STACK_VALUE(lhs), ACC);
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpInstanceOf)
@@ -1294,17 +1179,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
int a = ACC.int_32();
if (a == 0 || a == std::numeric_limits<int>::min()) {
acc = Encode(-static_cast<double>(a));
- traceDoubleValue(function, traceSlot);
} else {
- acc = sub_int32(0, ACC.int_32(), function->traceInfo(traceSlot));
+ acc = sub_int32(0, ACC.int_32());
}
} else if (ACC.isDouble()) {
acc ^= (1ull << 63); // simply flip sign bit
- traceDoubleValue(function, traceSlot);
} else {
acc = Encode(-ACC.toNumberImpl());
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(UMinus)
@@ -1315,57 +1197,49 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(Increment)
if (Q_LIKELY(ACC.integerCompatible())) {
- acc = add_int32(ACC.int_32(), 1, function->traceInfo(traceSlot));
+ acc = add_int32(ACC.int_32(), 1);
} else if (ACC.isDouble()) {
acc = QV4::Encode(ACC.doubleValue() + 1.);
- traceDoubleValue(function, traceSlot);
} else {
acc = Encode(ACC.toNumberImpl() + 1.);
CHECK_EXCEPTION;
- traceDoubleValue(function, traceSlot);
}
MOTH_END_INSTR(Increment)
MOTH_BEGIN_INSTR(Decrement)
if (Q_LIKELY(ACC.integerCompatible())) {
- acc = sub_int32(ACC.int_32(), 1, function->traceInfo(traceSlot));
+ acc = sub_int32(ACC.int_32(), 1);
} else if (ACC.isDouble()) {
acc = QV4::Encode(ACC.doubleValue() - 1.);
- traceDoubleValue(function, traceSlot);
} else {
acc = Encode(ACC.toNumberImpl() - 1.);
CHECK_EXCEPTION;
- traceDoubleValue(function, traceSlot);
}
MOTH_END_INSTR(Decrement)
MOTH_BEGIN_INSTR(Add)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
- acc = add_int32(left.int_32(), ACC.int_32(), function->traceInfo(traceSlot));
+ acc = add_int32(left.int_32(), ACC.int_32());
} else if (left.isNumber() && ACC.isNumber()) {
acc = Encode(left.asDouble() + ACC.asDouble());
- traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_add(engine, left, accumulator);
+ acc = Runtime::Add::call(engine, left, accumulator);
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(Add)
MOTH_BEGIN_INSTR(Sub)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
- acc = sub_int32(left.int_32(), ACC.int_32(), function->traceInfo(traceSlot));
+ acc = sub_int32(left.int_32(), ACC.int_32());
} else if (left.isNumber() && ACC.isNumber()) {
acc = Encode(left.asDouble() - ACC.asDouble());
- traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_sub(left, accumulator);
+ acc = Runtime::Sub::call(left, accumulator);
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(Sub)
@@ -1382,29 +1256,26 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_BEGIN_INSTR(Mul)
const Value left = STACK_VALUE(lhs);
if (Q_LIKELY(Value::integerCompatible(left, ACC))) {
- acc = mul_int32(left.int_32(), ACC.int_32(), function->traceInfo(traceSlot));
+ acc = mul_int32(left.int_32(), ACC.int_32());
} else if (left.isNumber() && ACC.isNumber()) {
acc = Encode(left.asDouble() * ACC.asDouble());
- traceDoubleValue(function, traceSlot);
} else {
STORE_ACC();
- acc = Runtime::method_mul(left, accumulator);
+ acc = Runtime::Mul::call(left, accumulator);
CHECK_EXCEPTION;
- traceOtherValue(function, traceSlot);
}
MOTH_END_INSTR(Mul)
MOTH_BEGIN_INSTR(Div)
STORE_ACC();
- acc = Runtime::method_div(STACK_VALUE(lhs), accumulator);
+ acc = Runtime::Div::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
MOTH_END_INSTR(Div)
MOTH_BEGIN_INSTR(Mod)
STORE_ACC();
- acc = Runtime::method_mod(STACK_VALUE(lhs), accumulator);
+ acc = Runtime::Mod::call(STACK_VALUE(lhs), accumulator);
CHECK_EXCEPTION;
- traceValue(acc, function, traceSlot);
MOTH_END_INSTR(Mod)
MOTH_BEGIN_INSTR(BitAnd)
@@ -1491,7 +1362,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(ThrowOnNullOrUndefined)
MOTH_BEGIN_INSTR(GetTemplateObject)
- acc = RuntimeHelpers::getTemplateObject(function, index);
+ acc = Runtime::GetTemplateObject::call(function, index);
MOTH_END_INSTR(GetTemplateObject)
MOTH_BEGIN_INSTR(Debug)
@@ -1502,7 +1373,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(Debug)
handleUnwind:
- Q_ASSERT(engine->hasException || frame->unwindLevel);
+ // We do start the exception handler in case of isInterrupted. The exception handler will
+ // immediately abort, due to the same isInterrupted. We don't skip the exception handler
+ // because the current behavior is easier to implement in the JIT.
+ Q_ASSERT(engine->hasException || engine->isInterrupted || frame->unwindLevel);
if (!frame->unwindHandler) {
acc = Encode::undefined();
return acc;
diff --git a/src/qml/jsruntime/qv4vtable_p.h b/src/qml/jsruntime/qv4vtable_p.h
index aff1ae82d7..9dda104cd1 100644
--- a/src/qml/jsruntime/qv4vtable_p.h
+++ b/src/qml/jsruntime/qv4vtable_p.h
@@ -58,7 +58,7 @@ namespace QV4 {
struct Lookup;
-struct OwnPropertyKeyIterator {
+struct Q_QML_PRIVATE_EXPORT OwnPropertyKeyIterator {
virtual ~OwnPropertyKeyIterator() = 0;
virtual PropertyKey next(const Object *o, Property *p = nullptr, PropertyAttributes *attrs = nullptr) = 0;
};
@@ -90,8 +90,8 @@ struct VTable
typedef bool (*ResolveLookupSetter)(Object *, ExecutionEngine *, Lookup *, const Value &);
const VTable * const parent;
- quint32 inlinePropertyOffset : 16;
- quint32 nInlineProperties : 16;
+ quint16 inlinePropertyOffset;
+ quint16 nInlineProperties;
quint8 isExecutionContext;
quint8 isString;
quint8 isObject;