aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4engine_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4engine_p.h')
-rw-r--r--src/qml/jsruntime/qv4engine_p.h344
1 files changed, 260 insertions, 84 deletions
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index d233347060..0958ab3ab5 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QV4ENGINE_H
#define QV4ENGINE_H
@@ -50,20 +14,21 @@
// We mean it.
//
-#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/qqmldelayedcallqueue_p.h>
-#include <QtCore/qelapsedtimer.h>
-#include <QtCore/qmutex.h>
-
-#include "qv4function_p.h"
+#include <private/qqmlrefcount_p.h>
#include <private/qv4compileddata_p.h>
+#include <private/qv4context_p.h>
+#include <private/qv4enginebase_p.h>
#include <private/qv4executablecompilationunit_p.h>
+#include <private/qv4function_p.h>
+#include <private/qv4global_p.h>
+#include <private/qv4stacklimits_p.h>
+
+#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qprocessordetection.h>
+#include <QtCore/qset.h>
namespace WTF {
class BumpPointerAllocator;
@@ -91,7 +56,18 @@ class PageAllocation;
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(qml_network)
+class QNetworkAccessManager;
+
+namespace QV4 {
+struct QObjectMethod;
+namespace detail {
+QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine);
+}
+}
+#else
namespace QV4 { struct QObjectMethod; }
+#endif // qml_network
// Used to allow a QObject method take and return raw V4 handles without having to expose
// 48 in the public API.
@@ -99,7 +75,7 @@ namespace QV4 { struct QObjectMethod; }
// class MyClass : public QObject {
// Q_OBJECT
// ...
-// Q_INVOKABLE void myMethod(QQmlV4Function*);
+// Q_INVOKABLE void myMethod(QQmlV4FunctionPtr);
// };
// 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
@@ -133,6 +109,7 @@ class QQmlError;
class QJSEngine;
class QQmlEngine;
class QQmlContextData;
+class QQmlTypeLoader;
namespace QV4 {
namespace Debugging {
@@ -158,12 +135,24 @@ class ReactionHandler;
struct Q_QML_EXPORT ExecutionEngine : public EngineBase
{
private:
- static qint32 maxCallDepth;
-
friend struct ExecutionContextSaver;
friend struct ExecutionContext;
friend struct Heap::ExecutionContext;
public:
+ enum class DiskCache {
+ Disabled = 0,
+ AotByteCode = 1 << 0,
+ AotNative = 1 << 1,
+ QmlcRead = 1 << 2,
+ QmlcWrite = 1 << 3,
+ Aot = AotByteCode | AotNative,
+ Qmlc = QmlcRead | QmlcWrite,
+ Enabled = Aot | Qmlc,
+
+ };
+
+ Q_DECLARE_FLAGS(DiskCacheOptions, DiskCache);
+
ExecutableAllocator *executableAllocator;
ExecutableAllocator *regExpAllocator;
@@ -185,6 +174,14 @@ public:
QQmlEngine *qmlEngine() const { return m_qmlEngine; }
QJSEngine *publicEngine;
+ template<typename TypeLoader = QQmlTypeLoader>
+ TypeLoader *typeLoader()
+ {
+ if (m_qmlEngine)
+ return TypeLoader::get(m_qmlEngine);
+ return nullptr;
+ }
+
enum JSObjects {
RootContext,
ScriptContext,
@@ -210,9 +207,7 @@ public:
URIErrorProto,
PromiseProto,
VariantProto,
-#if QT_CONFIG(qml_sequence_object)
SequenceProto,
-#endif
SharedArrayBufferProto,
ArrayBufferProto,
DataViewProto,
@@ -222,6 +217,7 @@ public:
MapProto,
IntrinsicTypedArrayProto,
ValueTypeProto,
+ TypeWrapperProto,
SignalHandlerProto,
IteratorProto,
ForInIteratorProto,
@@ -229,6 +225,8 @@ public:
MapIteratorProto,
ArrayIteratorProto,
StringIteratorProto,
+ UrlProto,
+ UrlSearchParamsProto,
Object_Ctor,
String_Ctor,
@@ -256,6 +254,8 @@ public:
WeakMap_Ctor,
Map_Ctor,
IntrinsicTypedArray_Ctor,
+ Url_Ctor,
+ UrlSearchParams_Ctor,
GetSymbolSpecies,
@@ -296,6 +296,14 @@ public:
FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
+ FunctionObject *urlCtor() const
+ {
+ return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor);
+ }
+ FunctionObject *urlSearchParamsCtor() const
+ {
+ return reinterpret_cast<FunctionObject *>(jsObjects + UrlSearchParams_Ctor);
+ }
FunctionObject *typedArrayCtors;
FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
@@ -321,9 +329,7 @@ public:
Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
Object *promisePrototype() const { return reinterpret_cast<Object *>(jsObjects + PromiseProto); }
Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
-#if QT_CONFIG(qml_sequence_object)
Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
-#endif
Object *sharedArrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + SharedArrayBufferProto); }
Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
@@ -337,17 +343,24 @@ public:
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
+ Object *typeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeWrapperProto); }
Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
Object *setIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SetIteratorProto); }
Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
+ Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); }
+ Object *urlSearchParamsPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlSearchParamsProto); }
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
+#if QT_CONFIG(qml_network)
+ QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager;
+#endif
+
enum JSStrings {
String_Empty,
String_undefined,
@@ -485,8 +498,6 @@ public:
Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
Symbol *symbol_revokableProxy() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_revokableProxy); }
- QIntrusiveList<ExecutableCompilationUnit, &ExecutableCompilationUnit::nextCompilationUnit> compilationUnits;
-
quint32 m_engineId;
RegExpCache *regExpCache;
@@ -499,7 +510,8 @@ public:
// calling preserve() on the object which removes it from this scarceResource list.
class ScarceResourceData {
public:
- ScarceResourceData(const QVariant &data = QVariant()) : data(data) {}
+ ScarceResourceData() = default;
+ ScarceResourceData(const QMetaType type, const void *data) : data(type, data) {}
QVariant data;
QIntrusiveListNode node;
};
@@ -532,7 +544,14 @@ public:
void setProfiler(Profiling::Profiler *profiler);
#endif // QT_CONFIG(qml_debug)
- ExecutionContext *currentContext() const;
+ // We don't want to #include <private/qv4stackframe_p.h> here, but we still want
+ // currentContext() to be inline. Therefore we shift the requirement to provide the
+ // complete type of CppStackFrame to the caller by making this a template.
+ template<typename StackFrame = CppStackFrame>
+ ExecutionContext *currentContext() const
+ {
+ return static_cast<const StackFrame *>(currentStackFrame)->context();
+ }
// ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
quintptr newProtoId() { return (protoIdCount += 2); }
@@ -542,6 +561,7 @@ public:
Heap::Object *newObject();
Heap::Object *newObject(Heap::InternalClass *internalClass);
+ Heap::String *newString(char16_t c) { return newString(QChar(c)); }
Heap::String *newString(const QString &s = QString());
Heap::String *newIdentifier(const QString &text);
@@ -558,17 +578,22 @@ public:
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
Heap::ArrayBuffer *newArrayBuffer(size_t length);
- Heap::DateObject *newDateObject(const Value &value);
- Heap::DateObject *newDateObject(const QDateTime &dt);
- Heap::DateObject *newDateObjectFromTime(const QTime &t);
+ Heap::DateObject *newDateObject(double dateTime);
+ Heap::DateObject *newDateObject(const QDateTime &dateTime);
+ Heap::DateObject *newDateObject(QDate date, Heap::Object *parent, int index, uint flags);
+ Heap::DateObject *newDateObject(QTime time, Heap::Object *parent, int index, uint flags);
+ Heap::DateObject *newDateObject(QDateTime dateTime, Heap::Object *parent, int index, uint flags);
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::UrlObject *newUrlObject();
+ Heap::UrlObject *newUrlObject(const QUrl &url);
+ Heap::UrlSearchParamsObject *newUrlSearchParamsObject();
+
Heap::Object *newErrorObject(const Value &value);
Heap::Object *newErrorObject(const QString &message);
Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
@@ -585,16 +610,35 @@ public:
Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability);
Promise::ReactionHandler *getPromiseReactionHandler();
- Heap::Object *newVariantObject(const QVariant &v);
+ Heap::Object *newVariantObject(const QMetaType type, const void *data);
Heap::Object *newForInIteratorObject(Object *o);
Heap::Object *newSetIteratorObject(Object *o);
Heap::Object *newMapIteratorObject(Object *o);
Heap::Object *newArrayIteratorObject(Object *o);
+ static Heap::ExecutionContext *qmlContext(Heap::ExecutionContext *ctx)
+ {
+ Heap::ExecutionContext *outer = ctx->outer;
+
+ if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !outer)
+ return nullptr;
+
+ while (outer && outer->type != Heap::ExecutionContext::Type_GlobalContext) {
+ ctx = outer;
+ outer = ctx->outer;
+ }
+
+ Q_ASSERT(ctx);
+ if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
+ return nullptr;
+
+ return ctx;
+ }
+
Heap::QmlContext *qmlContext() const;
QObject *qmlScopeObject() const;
- QQmlContextData *callingQmlContext() const;
+ QQmlRefPointer<QQmlContextData> callingQmlContext() const;
StackTrace stackTrace(int frameLimit = -1) const;
@@ -628,26 +672,34 @@ public:
QQmlError catchExceptionAsQmlError();
// variant conversions
- QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
+ static QVariant toVariant(
+ const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols = true);
+ static QVariant toVariantLossy(const QV4::Value &value);
QV4::ReturnedValue fromVariant(const QVariant &);
+ QV4::ReturnedValue fromVariant(
+ const QVariant &variant, Heap::Object *parent, int property, uint flags);
- QVariantMap variantMapFromJS(const QV4::Object *o);
+ static QVariantMap variantMapFromJS(const QV4::Object *o);
- bool metaTypeFromJS(const Value *value, int type, void *data);
- QV4::ReturnedValue metaTypeToJS(int type, const void *data);
+ static bool metaTypeFromJS(const Value &value, QMetaType type, void *data);
+ QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data);
int maxJSStackSize() const;
int maxGCStackSize() const;
bool checkStackLimits();
+ int safeForAllocLength(qint64 len64);
bool canJIT(Function *f = nullptr)
{
#if QT_CONFIG(qml_jit)
if (!m_canAllocateExecutableMemory)
return false;
- if (f)
- return !f->isGenerator() && f->interpreterCallCount >= jitCallCountThreshold;
+ if (f) {
+ return f->kind != Function::AotCompiled
+ && !f->isGenerator()
+ && f->interpreterCallCount >= s_jitCallCountThreshold;
+ }
return true;
#else
Q_UNUSED(f);
@@ -658,8 +710,10 @@ public:
QV4::ReturnedValue global();
void initQmlGlobalObject();
void initializeGlobal();
+ void createQtObject();
void freezeObject(const QV4::Value &value);
+ void lockObject(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;
@@ -689,7 +743,7 @@ public:
void setExtensionData(int, Deletable *);
Deletable *extensionData(int index) const
{
- if (index < m_extensionData.count())
+ if (index < m_extensionData.size())
return m_extensionData[index];
else
return nullptr;
@@ -701,19 +755,117 @@ public:
QQmlRefPointer<ExecutableCompilationUnit> compileModule(
const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp);
- mutable QMutex moduleMutex;
- QHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> modules;
- void injectModule(const QQmlRefPointer<ExecutableCompilationUnit> &moduleUnit);
- QQmlRefPointer<ExecutableCompilationUnit> moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
- QQmlRefPointer<ExecutableCompilationUnit> loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
+ QQmlRefPointer<ExecutableCompilationUnit> compilationUnitForUrl(const QUrl &url) const;
+
+ QQmlRefPointer<ExecutableCompilationUnit> executableCompilationUnit(
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit);
+
+ QQmlRefPointer<ExecutableCompilationUnit> insertCompilationUnit(
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit);
+
+ QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> compilationUnits() const
+ {
+ return m_compilationUnits;
+ }
+ void clearCompilationUnits() { m_compilationUnits.clear(); }
+ void trimCompilationUnits();
+
+ QV4::Value *registerNativeModule(const QUrl &url, const QV4::Value &module);
+
+ struct Module {
+ QQmlRefPointer<ExecutableCompilationUnit> compiled;
+
+ // We can pass a raw value pointer here, but nowhere else. See below.
+ Value *native = nullptr;
+ };
+
+ Module moduleForUrl(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr) const;
+ Module loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr);
+
+ DiskCacheOptions diskCacheOptions() const;
+
+ void callInContext(QV4::Function *function, QObject *self, QV4::ExecutionContext *ctxt,
+ int argc, void **args, QMetaType *types);
+ QV4::ReturnedValue callInContext(QV4::Function *function, QObject *self,
+ QV4::ExecutionContext *ctxt, int argc, const QV4::Value *argv);
+
+ QV4::ReturnedValue fromData(
+ QMetaType type, const void *ptr,
+ Heap::Object *parent = nullptr, int property = -1, uint flags = 0);
+
+
+ static void setMaxCallDepth(int maxCallDepth) { s_maxCallDepth = maxCallDepth; }
+ static int maxCallDepth() { return s_maxCallDepth; }
+
+ template<typename Value>
+ static QJSPrimitiveValue createPrimitive(const Value &v)
+ {
+ if (v->isUndefined())
+ return QJSPrimitiveValue(QJSPrimitiveUndefined());
+ if (v->isNull())
+ return QJSPrimitiveValue(QJSPrimitiveNull());
+ if (v->isBoolean())
+ return QJSPrimitiveValue(v->toBoolean());
+ if (v->isInteger())
+ return QJSPrimitiveValue(v->integerValue());
+ if (v->isDouble())
+ return QJSPrimitiveValue(v->doubleValue());
+ bool ok;
+ const QString result = v->toQString(&ok);
+ return ok ? QJSPrimitiveValue(result) : QJSPrimitiveValue(QJSPrimitiveUndefined());
+ }
private:
+ template<int Frames>
+ friend struct ExecutionEngineCallDepthRecorder;
+
+ static void initializeStaticMembers();
+
+ bool inStack(const void *current) const
+ {
+#if Q_STACK_GROWTH_DIRECTION > 0
+ return current < cppStackLimit && current >= cppStackBase;
+#else
+ return current > cppStackLimit && current <= cppStackBase;
+#endif
+ }
+
+ bool hasCppStackOverflow()
+ {
+ if (s_maxCallDepth >= 0)
+ return callDepth >= s_maxCallDepth;
+
+ if (inStack(currentStackPointer()))
+ return false;
+
+ // Double check the stack limits on failure.
+ // We may have moved to a different thread.
+ const StackProperties stack = stackProperties();
+ cppStackBase = stack.base;
+ cppStackLimit = stack.softLimit;
+ return !inStack(currentStackPointer());
+ }
+
+ bool hasJsStackOverflow() const
+ {
+ return jsStackTop > jsStackLimit;
+ }
+
+ bool hasStackOverflow()
+ {
+ return hasJsStackOverflow() || hasCppStackOverflow();
+ }
+
+ static int s_maxCallDepth;
+ static int s_jitCallCountThreshold;
+ static int s_maxJSStackSize;
+ static int s_maxGCStackSize;
+
#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;
@@ -733,24 +885,46 @@ private:
QVector<Deletable *> m_extensionData;
- int m_maxJSStackSize = 4 * 1024 * 1024;
- int m_maxGCStackSize = 2 * 1024 * 1024;
+ QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> m_compilationUnits;
+
+ // QV4::PersistentValue would be preferred, but using QHash will create copies,
+ // and QV4::PersistentValue doesn't like creating copies.
+ // Instead, we allocate a raw pointer using the same manual memory management
+ // technique in QV4::PersistentValue.
+ QHash<QUrl, Value *> nativeModules;
};
-#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
+#define CHECK_STACK_LIMITS(v4) \
+ if (v4->checkStackLimits()) \
+ return Encode::undefined(); \
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
+template<int Frames = 1>
struct ExecutionEngineCallDepthRecorder
{
ExecutionEngine *ee;
- ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
- ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
+ ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e)
+ {
+ if (ExecutionEngine::s_maxCallDepth >= 0)
+ ee->callDepth += Frames;
+ }
+
+ ~ExecutionEngineCallDepthRecorder()
+ {
+ if (ExecutionEngine::s_maxCallDepth >= 0)
+ ee->callDepth -= Frames;
+ }
+
+ bool hasOverflow() const
+ {
+ return ee->hasCppStackOverflow();
+ }
};
inline bool ExecutionEngine::checkStackLimits()
{
- if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
+ if (Q_UNLIKELY(hasStackOverflow())) {
throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
return true;
}
@@ -758,6 +932,8 @@ inline bool ExecutionEngine::checkStackLimits()
return false;
}
+Q_DECLARE_OPERATORS_FOR_FLAGS(ExecutionEngine::DiskCacheOptions);
+
} // namespace QV4
QT_END_NAMESPACE