/**************************************************************************** ** ** 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$ ** ****************************************************************************/ #ifndef QV4ENGINE_H #define QV4ENGINE_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 "qv4global_p.h" #include "qv4managed_p.h" #include "qv4context_p.h" #include #include "qv4enginebase_p.h" #include #include #ifndef V4_BOOTSTRAP # include "qv4function_p.h" # include # include #endif namespace WTF { class BumpPointerAllocator; class PageAllocation; } QT_BEGIN_NAMESPACE class QV8Engine; class QQmlError; class QJSEngine; class QQmlEngine; class QQmlContextData; namespace QV4 { namespace Debugging { class Debugger; } // namespace Debugging namespace Profiling { class Profiler; } // namespace Profiling namespace CompiledData { struct CompilationUnit; } namespace Heap { struct Module; }; struct Function; namespace Promise { class ReactionHandler; }; struct Q_QML_EXPORT ExecutionEngine : public EngineBase { private: static qint32 maxCallDepth; friend struct ExecutionContextSaver; friend struct ExecutionContext; friend struct Heap::ExecutionContext; public: ExecutableAllocator *executableAllocator; ExecutableAllocator *regExpAllocator; WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine. enum { JSStackLimit = 4*1024*1024, GCStackLimit = 2*1024*1024 }; WTF::PageAllocation *jsStack; WTF::PageAllocation *gcStack; QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) { Value *ptr = jsStackTop; jsStackTop = ptr + nValues; return ptr; } 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; QJSEngine *publicEngine; enum JSObjects { RootContext, ScriptContext, IntegerNull, // Has to come after the RootContext to make the context stack safe ObjectProto, SymbolProto, ArrayProto, ArrayProtoValues, PropertyListProto, StringProto, NumberProto, BooleanProto, DateProto, FunctionProto, GeneratorProto, RegExpProto, ErrorProto, EvalErrorProto, RangeErrorProto, ReferenceErrorProto, SyntaxErrorProto, TypeErrorProto, URIErrorProto, PromiseProto, VariantProto, #if QT_CONFIG(qml_sequence_object) SequenceProto, #endif SharedArrayBufferProto, ArrayBufferProto, DataViewProto, WeakSetProto, SetProto, WeakMapProto, MapProto, IntrinsicTypedArrayProto, ValueTypeProto, SignalHandlerProto, IteratorProto, ForInIteratorProto, SetIteratorProto, MapIteratorProto, ArrayIteratorProto, StringIteratorProto, Object_Ctor, String_Ctor, Symbol_Ctor, Number_Ctor, Boolean_Ctor, Array_Ctor, Function_Ctor, GeneratorFunction_Ctor, Date_Ctor, RegExp_Ctor, Error_Ctor, EvalError_Ctor, RangeError_Ctor, ReferenceError_Ctor, SyntaxError_Ctor, TypeError_Ctor, URIError_Ctor, SharedArrayBuffer_Ctor, Promise_Ctor, ArrayBuffer_Ctor, DataView_Ctor, WeakSet_Ctor, Set_Ctor, WeakMap_Ctor, Map_Ctor, IntrinsicTypedArray_Ctor, GetSymbolSpecies, Eval_Function, GetStack_Function, ThrowerObject, NJSObjects }; Value *jsObjects; enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency ExecutionContext *rootContext() const { return reinterpret_cast(jsObjects + RootContext); } ExecutionContext *scriptContext() const { return reinterpret_cast(jsObjects + ScriptContext); } void setScriptContext(ReturnedValue c) { jsObjects[ScriptContext] = c; } FunctionObject *objectCtor() const { return reinterpret_cast(jsObjects + Object_Ctor); } FunctionObject *stringCtor() const { return reinterpret_cast(jsObjects + String_Ctor); } FunctionObject *symbolCtor() const { return reinterpret_cast(jsObjects + Symbol_Ctor); } FunctionObject *numberCtor() const { return reinterpret_cast(jsObjects + Number_Ctor); } FunctionObject *booleanCtor() const { return reinterpret_cast(jsObjects + Boolean_Ctor); } FunctionObject *arrayCtor() const { return reinterpret_cast(jsObjects + Array_Ctor); } FunctionObject *functionCtor() const { return reinterpret_cast(jsObjects + Function_Ctor); } FunctionObject *generatorFunctionCtor() const { return reinterpret_cast(jsObjects + GeneratorFunction_Ctor); } FunctionObject *dateCtor() const { return reinterpret_cast(jsObjects + Date_Ctor); } FunctionObject *regExpCtor() const { return reinterpret_cast(jsObjects + RegExp_Ctor); } FunctionObject *errorCtor() const { return reinterpret_cast(jsObjects + Error_Ctor); } FunctionObject *evalErrorCtor() const { return reinterpret_cast(jsObjects + EvalError_Ctor); } FunctionObject *rangeErrorCtor() const { return reinterpret_cast(jsObjects + RangeError_Ctor); } FunctionObject *referenceErrorCtor() const { return reinterpret_cast(jsObjects + ReferenceError_Ctor); } FunctionObject *syntaxErrorCtor() const { return reinterpret_cast(jsObjects + SyntaxError_Ctor); } FunctionObject *typeErrorCtor() const { return reinterpret_cast(jsObjects + TypeError_Ctor); } FunctionObject *uRIErrorCtor() const { return reinterpret_cast(jsObjects + URIError_Ctor); } FunctionObject *sharedArrayBufferCtor() const { return reinterpret_cast(jsObjects + SharedArrayBuffer_Ctor); } FunctionObject *promiseCtor() const { return reinterpret_cast(jsObjects + Promise_Ctor); } FunctionObject *arrayBufferCtor() const { return reinterpret_cast(jsObjects + ArrayBuffer_Ctor); } FunctionObject *dataViewCtor() const { return reinterpret_cast(jsObjects + DataView_Ctor); } FunctionObject *weakSetCtor() const { return reinterpret_cast(jsObjects + WeakSet_Ctor); } FunctionObject *setCtor() const { return reinterpret_cast(jsObjects + Set_Ctor); } FunctionObject *weakMapCtor() const { return reinterpret_cast(jsObjects + WeakMap_Ctor); } FunctionObject *mapCtor() const { return reinterpret_cast(jsObjects + Map_Ctor); } FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast(jsObjects + IntrinsicTypedArray_Ctor); } FunctionObject *typedArrayCtors; FunctionObject *getSymbolSpecies() const { return reinterpret_cast(jsObjects + GetSymbolSpecies); } Object *objectPrototype() const { return reinterpret_cast(jsObjects + ObjectProto); } Object *symbolPrototype() const { return reinterpret_cast(jsObjects + SymbolProto); } Object *arrayPrototype() const { return reinterpret_cast(jsObjects + ArrayProto); } Object *arrayProtoValues() const { return reinterpret_cast(jsObjects + ArrayProtoValues); } Object *propertyListPrototype() const { return reinterpret_cast(jsObjects + PropertyListProto); } Object *stringPrototype() const { return reinterpret_cast(jsObjects + StringProto); } Object *numberPrototype() const { return reinterpret_cast(jsObjects + NumberProto); } Object *booleanPrototype() const { return reinterpret_cast(jsObjects + BooleanProto); } Object *datePrototype() const { return reinterpret_cast(jsObjects + DateProto); } Object *functionPrototype() const { return reinterpret_cast(jsObjects + FunctionProto); } Object *generatorPrototype() const { return reinterpret_cast(jsObjects + GeneratorProto); } Object *regExpPrototype() const { return reinterpret_cast(jsObjects + RegExpProto); } Object *errorPrototype() const { return reinterpret_cast(jsObjects + ErrorProto); } Object *evalErrorPrototype() const { return reinterpret_cast(jsObjects + EvalErrorProto); } Object *rangeErrorPrototype() const { return reinterpret_cast(jsObjects + RangeErrorProto); } Object *referenceErrorPrototype() const { return reinterpret_cast(jsObjects + ReferenceErrorProto); } Object *syntaxErrorPrototype() const { return reinterpret_cast(jsObjects + SyntaxErrorProto); } Object *typeErrorPrototype() const { return reinterpret_cast(jsObjects + TypeErrorProto); } Object *uRIErrorPrototype() const { return reinterpret_cast(jsObjects + URIErrorProto); } Object *promisePrototype() const { return reinterpret_cast(jsObjects + PromiseProto); } Object *variantPrototype() const { return reinterpret_cast(jsObjects + VariantProto); } #if QT_CONFIG(qml_sequence_object) Object *sequencePrototype() const { return reinterpret_cast(jsObjects + SequenceProto); } #endif Object *sharedArrayBufferPrototype() const { return reinterpret_cast(jsObjects + SharedArrayBufferProto); } Object *arrayBufferPrototype() const { return reinterpret_cast(jsObjects + ArrayBufferProto); } Object *dataViewPrototype() const { return reinterpret_cast(jsObjects + DataViewProto); } Object *weakSetPrototype() const { return reinterpret_cast(jsObjects + WeakSetProto); } Object *setPrototype() const { return reinterpret_cast(jsObjects + SetProto); } Object *weakMapPrototype() const { return reinterpret_cast(jsObjects + WeakMapProto); } Object *mapPrototype() const { return reinterpret_cast(jsObjects + MapProto); } Object *intrinsicTypedArrayPrototype() const { return reinterpret_cast(jsObjects + IntrinsicTypedArrayProto); } Object *typedArrayPrototype; Object *valueTypeWrapperPrototype() const { return reinterpret_cast(jsObjects + ValueTypeProto); } Object *signalHandlerPrototype() const { return reinterpret_cast(jsObjects + SignalHandlerProto); } Object *iteratorPrototype() const { return reinterpret_cast(jsObjects + IteratorProto); } Object *forInIteratorPrototype() const { return reinterpret_cast(jsObjects + ForInIteratorProto); } Object *setIteratorPrototype() const { return reinterpret_cast(jsObjects + SetIteratorProto); } Object *mapIteratorPrototype() const { return reinterpret_cast(jsObjects + MapIteratorProto); } Object *arrayIteratorPrototype() const { return reinterpret_cast(jsObjects + ArrayIteratorProto); } Object *stringIteratorPrototype() const { return reinterpret_cast(jsObjects + StringIteratorProto); } EvalFunction *evalFunction() const { return reinterpret_cast(jsObjects + Eval_Function); } FunctionObject *getStackFunction() const { return reinterpret_cast(jsObjects + GetStack_Function); } FunctionObject *thrower() const { return reinterpret_cast(jsObjects + ThrowerObject); } enum JSStrings { String_Empty, String_undefined, String_null, String_true, String_false, String_boolean, String_number, String_string, String_default, String_symbol, String_object, String_function, String_length, String_prototype, String_constructor, String_arguments, String_caller, String_callee, String_this, String___proto__, String_enumerable, String_configurable, String_writable, String_value, String_get, String_set, String_eval, String_uintMax, String_name, String_index, String_input, String_toString, String_toLocaleString, String_destroy, String_valueOf, String_byteLength, String_byteOffset, String_buffer, String_lastIndex, String_next, String_done, String_return, String_throw, String_global, String_ignoreCase, String_multiline, String_unicode, String_sticky, String_source, String_flags, NJSStrings }; Value *jsStrings; enum JSSymbols { Symbol_hasInstance, Symbol_isConcatSpreadable, Symbol_iterator, Symbol_match, Symbol_replace, Symbol_search, Symbol_species, Symbol_split, Symbol_toPrimitive, Symbol_toStringTag, Symbol_unscopables, Symbol_revokableProxy, NJSSymbols }; Value *jsSymbols; String *id_empty() const { return reinterpret_cast(jsStrings + String_Empty); } String *id_undefined() const { return reinterpret_cast(jsStrings + String_undefined); } String *id_null() const { return reinterpret_cast(jsStrings + String_null); } String *id_true() const { return reinterpret_cast(jsStrings + String_true); } String *id_false() const { return reinterpret_cast(jsStrings + String_false); } String *id_boolean() const { return reinterpret_cast(jsStrings + String_boolean); } String *id_number() const { return reinterpret_cast(jsStrings + String_number); } String *id_string() const { return reinterpret_cast(jsStrings + String_string); } String *id_default() const { return reinterpret_cast(jsStrings + String_default); } String *id_symbol() const { return reinterpret_cast(jsStrings + String_symbol); } String *id_object() const { return reinterpret_cast(jsStrings + String_object); } String *id_function() const { return reinterpret_cast(jsStrings + String_function); } String *id_length() const { return reinterpret_cast(jsStrings + String_length); } String *id_prototype() const { return reinterpret_cast(jsStrings + String_prototype); } String *id_constructor() const { return reinterpret_cast(jsStrings + String_constructor); } String *id_arguments() const { return reinterpret_cast(jsStrings + String_arguments); } String *id_caller() const { return reinterpret_cast(jsStrings + String_caller); } String *id_callee() const { return reinterpret_cast(jsStrings + String_callee); } String *id_this() const { return reinterpret_cast(jsStrings + String_this); } String *id___proto__() const { return reinterpret_cast(jsStrings + String___proto__); } String *id_enumerable() const { return reinterpret_cast(jsStrings + String_enumerable); } String *id_configurable() const { return reinterpret_cast(jsStrings + String_configurable); } String *id_writable() const { return reinterpret_cast(jsStrings + String_writable); } String *id_value() const { return reinterpret_cast(jsStrings + String_value); } String *id_get() const { return reinterpret_cast(jsStrings + String_get); } String *id_set() const { return reinterpret_cast(jsStrings + String_set); } String *id_eval() const { return reinterpret_cast(jsStrings + String_eval); } String *id_uintMax() const { return reinterpret_cast(jsStrings + String_uintMax); } String *id_name() const { return reinterpret_cast(jsStrings + String_name); } String *id_index() const { return reinterpret_cast(jsStrings + String_index); } String *id_input() const { return reinterpret_cast(jsStrings + String_input); } String *id_toString() const { return reinterpret_cast(jsStrings + String_toString); } String *id_toLocaleString() const { return reinterpret_cast(jsStrings + String_toLocaleString); } String *id_destroy() const { return reinterpret_cast(jsStrings + String_destroy); } String *id_valueOf() const { return reinterpret_cast(jsStrings + String_valueOf); } String *id_byteLength() const { return reinterpret_cast(jsStrings + String_byteLength); } String *id_byteOffset() const { return reinterpret_cast(jsStrings + String_byteOffset); } String *id_buffer() const { return reinterpret_cast(jsStrings + String_buffer); } String *id_lastIndex() const { return reinterpret_cast(jsStrings + String_lastIndex); } String *id_next() const { return reinterpret_cast(jsStrings + String_next); } String *id_done() const { return reinterpret_cast(jsStrings + String_done); } String *id_return() const { return reinterpret_cast(jsStrings + String_return); } String *id_throw() const { return reinterpret_cast(jsStrings + String_throw); } String *id_global() const { return reinterpret_cast(jsStrings + String_global); } String *id_ignoreCase() const { return reinterpret_cast(jsStrings + String_ignoreCase); } String *id_multiline() const { return reinterpret_cast(jsStrings + String_multiline); } String *id_unicode() const { return reinterpret_cast(jsStrings + String_unicode); } String *id_sticky() const { return reinterpret_cast(jsStrings + String_sticky); } String *id_source() const { return reinterpret_cast(jsStrings + String_source); } String *id_flags() const { return reinterpret_cast(jsStrings + String_flags); } Symbol *symbol_hasInstance() const { return reinterpret_cast(jsSymbols + Symbol_hasInstance); } Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast(jsSymbols + Symbol_isConcatSpreadable); } Symbol *symbol_iterator() const { return reinterpret_cast(jsSymbols + Symbol_iterator); } Symbol *symbol_match() const { return reinterpret_cast(jsSymbols + Symbol_match); } Symbol *symbol_replace() const { return reinterpret_cast(jsSymbols + Symbol_replace); } Symbol *symbol_search() const { return reinterpret_cast(jsSymbols + Symbol_search); } Symbol *symbol_species() const { return reinterpret_cast(jsSymbols + Symbol_species); } Symbol *symbol_split() const { return reinterpret_cast(jsSymbols + Symbol_split); } Symbol *symbol_toPrimitive() const { return reinterpret_cast(jsSymbols + Symbol_toPrimitive); } Symbol *symbol_toStringTag() const { return reinterpret_cast(jsSymbols + Symbol_toStringTag); } Symbol *symbol_unscopables() const { return reinterpret_cast(jsSymbols + Symbol_unscopables); } Symbol *symbol_revokableProxy() const { return reinterpret_cast(jsSymbols + Symbol_revokableProxy); } #ifndef V4_BOOTSTRAP QIntrusiveList compilationUnits; #endif quint32 m_engineId; RegExpCache *regExpCache; // Scarce resources are "exceptionally high cost" QVariant types where allowing the // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other // out-of-resource situations. When such a resource is passed into JavaScript we // add it to the scarceResources list and it is destroyed when we return from the // JavaScript execution that created it. The user can prevent this behavior by // calling preserve() on the object which removes it from this scarceResource list. class ScarceResourceData { public: ScarceResourceData(const QVariant &data = QVariant()) : data(data) {} QVariant data; QIntrusiveListNode node; }; QIntrusiveList scarceResources; // Normally the JS wrappers for QObjects are stored in the QQmlData/QObjectPrivate, // 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) const bool m_canAllocateExecutableMemory; #endif quintptr protoIdCount = 1; ExecutionEngine(QJSEngine *jsEngine = nullptr); ~ExecutionEngine(); #if !QT_CONFIG(qml_debug) QV4::Debugging::Debugger *debugger() const { return nullptr; } QV4::Profiling::Profiler *profiler() const { return nullptr; } void setDebugger(Debugging::Debugger *) {} void setProfiler(Profiling::Profiler *) {} #else QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); } QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); } void setDebugger(Debugging::Debugger *debugger); void setProfiler(Profiling::Profiler *profiler); #endif // QT_CONFIG(qml_debug) ExecutionContext *currentContext() const; // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast quintptr newProtoId() { return (protoIdCount += 2); } Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype); Heap::Object *newObject(); Heap::Object *newObject(Heap::InternalClass *internalClass); Heap::String *newString(const QString &s = QString()); Heap::String *newIdentifier(const QString &text); Heap::Object *newStringObject(const String *string); Heap::Object *newSymbolObject(const Symbol *symbol); Heap::Object *newNumberObject(double value); Heap::Object *newBooleanObject(bool b); Heap::ArrayObject *newArrayObject(int count = 0); Heap::ArrayObject *newArrayObject(const Value *values, int length); Heap::ArrayObject *newArrayObject(const QStringList &list); Heap::ArrayObject *newArrayObject(Heap::InternalClass *ic); 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::RegExpObject *newRegExpObject(const QString &pattern, int flags); Heap::RegExpObject *newRegExpObject(RegExp *re); Heap::RegExpObject *newRegExpObject(const QRegExp &re); 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); Heap::Object *newSyntaxErrorObject(const QString &message); Heap::Object *newReferenceErrorObject(const QString &message); Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column); Heap::Object *newTypeErrorObject(const QString &message); Heap::Object *newRangeErrorObject(const QString &message); Heap::Object *newURIErrorObject(const QString &message); Heap::Object *newURIErrorObject(const Value &message); Heap::Object *newEvalErrorObject(const QString &message); Heap::PromiseObject *newPromiseObject(); Heap::Object *newPromiseObject(const QV4::FunctionObject *thisObject, const QV4::PromiseCapability *capability); Promise::ReactionHandler *getPromiseReactionHandler(); Heap::Object *newVariantObject(const QVariant &v); Heap::Object *newForInIteratorObject(Object *o); Heap::Object *newSetIteratorObject(Object *o); Heap::Object *newMapIteratorObject(Object *o); Heap::Object *newArrayIteratorObject(Object *o); Heap::QmlContext *qmlContext() const; QObject *qmlScopeObject() const; QQmlContextData *callingQmlContext() const; StackTrace stackTrace(int frameLimit = -1) const; QUrl resolvedUrl(const QString &file); void markObjects(MarkStack *markStack); void initRootContext(); Heap::InternalClass *newClass(Heap::InternalClass *other); StackTrace exceptionStackTrace; ReturnedValue throwError(const Value &value); ReturnedValue catchException(StackTrace *trace = nullptr); ReturnedValue throwError(const QString &message); ReturnedValue throwSyntaxError(const QString &message); ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column); ReturnedValue throwTypeError(); ReturnedValue throwTypeError(const QString &message); ReturnedValue throwReferenceError(const Value &value); ReturnedValue throwReferenceError(const QString &name); ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column); ReturnedValue throwRangeError(const Value &value); ReturnedValue throwRangeError(const QString &message); ReturnedValue throwURIError(const Value &msg); ReturnedValue throwUnimplemented(const QString &message); // Use only inside catch(...) -- will re-throw if no JS exception QQmlError catchExceptionAsQmlError(); // variant conversions QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true); QV4::ReturnedValue fromVariant(const QVariant &); QVariantMap variantMapFromJS(const QV4::Object *o); bool metaTypeFromJS(const Value *value, int type, void *data); QV4::ReturnedValue metaTypeToJS(int type, const void *data); bool checkStackLimits(); bool canJIT(Function *f = nullptr) { #if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP) if (!m_canAllocateExecutableMemory) return false; if (f) return !f->isGenerator() && f->interpreterCallCount >= jitCallCountThreshold; return true; #else Q_UNUSED(f); return false; #endif } QV4::ReturnedValue global(); double localTZA = 0.0; // local timezone, initialized at startup static QQmlRefPointer compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList *diagnostics); #ifndef V4_BOOTSTRAP QQmlRefPointer compileModule(const QUrl &url); QQmlRefPointer compileModule(const QUrl &url, const QString &sourceCode, const QDateTime &sourceTimeStamp); mutable QMutex moduleMutex; QHash> modules; void injectModule(const QQmlRefPointer &moduleUnit); QQmlRefPointer moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const; QQmlRefPointer loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr); #endif private: #if QT_CONFIG(qml_debug) QScopedPointer m_debugger; QScopedPointer m_profiler; #endif int jitCallCountThreshold; // used by generated Promise objects to handle 'then' events QScopedPointer 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; #endif #define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \ ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4); struct ExecutionEngineCallDepthRecorder { ExecutionEngine *ee; ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; } ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; } }; inline bool ExecutionEngine::checkStackLimits() { if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) { throwRangeError(QStringLiteral("Maximum call stack size exceeded.")); return true; } return false; } } // namespace QV4 QT_END_NAMESPACE #endif // QV4ENGINE_H