2012-11-17 20:54:26 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2012-11-17 20:54:26 +00:00
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2012-11-17 20:54:26 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2012-11-17 20:54:26 +00:00
|
|
|
** 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
|
2015-01-28 11:55:39 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-19 09:38:36 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-11-17 20:54:26 +00:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2016-01-19 09:38:36 +00:00
|
|
|
** 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.
|
2012-11-17 20:54:26 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** 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.
|
2012-11-17 20:54:26 +00:00
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
2013-03-18 10:03:51 +00:00
|
|
|
#ifndef QV4ENGINE_H
|
|
|
|
#define QV4ENGINE_H
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2015-10-05 08:45:54 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
|
2013-04-15 09:50:16 +00:00
|
|
|
#include "qv4global_p.h"
|
2013-08-08 07:20:52 +00:00
|
|
|
#include "private/qv4isel_p.h"
|
2014-07-25 15:44:14 +00:00
|
|
|
#include "qv4managed_p.h"
|
2014-11-18 16:35:48 +00:00
|
|
|
#include "qv4context_p.h"
|
2015-10-08 10:59:40 +00:00
|
|
|
#include "qv4runtimeapi_p.h"
|
2013-05-14 00:01:04 +00:00
|
|
|
#include <private/qintrusivelist_p.h>
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2016-03-23 12:17:10 +00:00
|
|
|
#ifndef V4_BOOTSTRAP
|
|
|
|
# include <private/qv8engine_p.h>
|
|
|
|
#endif
|
|
|
|
|
2013-04-19 09:47:50 +00:00
|
|
|
namespace WTF {
|
|
|
|
class BumpPointerAllocator;
|
2013-09-03 10:40:07 +00:00
|
|
|
class PageAllocation;
|
2013-04-19 09:47:50 +00:00
|
|
|
}
|
2013-01-14 15:53:43 +00:00
|
|
|
|
2013-01-31 09:00:06 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2013-06-04 14:00:13 +00:00
|
|
|
class QV8Engine;
|
2013-10-17 06:56:51 +00:00
|
|
|
class QQmlError;
|
2014-12-30 14:31:09 +00:00
|
|
|
class QJSEngine;
|
2014-12-30 15:38:20 +00:00
|
|
|
class QQmlEngine;
|
2015-06-15 14:41:24 +00:00
|
|
|
class QQmlContextData;
|
2013-04-17 16:17:30 +00:00
|
|
|
|
2013-07-24 08:29:04 +00:00
|
|
|
namespace QV4 {
|
2012-11-29 13:41:26 +00:00
|
|
|
namespace Debugging {
|
|
|
|
class Debugger;
|
|
|
|
} // namespace Debugging
|
2014-01-22 16:46:20 +00:00
|
|
|
namespace Profiling {
|
|
|
|
class Profiler;
|
|
|
|
} // namespace Profiling
|
2013-08-15 12:11:19 +00:00
|
|
|
namespace CompiledData {
|
|
|
|
struct CompilationUnit;
|
|
|
|
}
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2016-06-29 14:05:12 +00:00
|
|
|
struct InternalClass;
|
|
|
|
struct InternalClassPool;
|
|
|
|
|
2013-04-16 15:03:00 +00:00
|
|
|
struct Q_QML_EXPORT ExecutionEngine
|
2012-11-17 20:54:26 +00:00
|
|
|
{
|
2013-11-21 15:41:32 +00:00
|
|
|
private:
|
2016-04-25 13:01:04 +00:00
|
|
|
static qint32 maxCallDepth;
|
|
|
|
|
2013-11-21 15:41:32 +00:00
|
|
|
friend struct ExecutionContextSaver;
|
|
|
|
friend struct ExecutionContext;
|
2014-11-01 22:24:13 +00:00
|
|
|
friend struct Heap::ExecutionContext;
|
2013-11-21 15:41:32 +00:00
|
|
|
public:
|
2014-11-28 08:31:10 +00:00
|
|
|
Heap::ExecutionContext *current;
|
2013-11-21 15:41:32 +00:00
|
|
|
|
2014-02-05 15:12:16 +00:00
|
|
|
Value *jsStackTop;
|
2017-02-06 09:57:04 +00:00
|
|
|
quint8 hasException;
|
|
|
|
quint8 writeBarrierActive = false;
|
|
|
|
quint16 unused = 0;
|
2016-04-25 13:01:04 +00:00
|
|
|
qint32 callDepth;
|
2013-03-14 13:03:04 +00:00
|
|
|
|
2014-02-05 15:12:16 +00:00
|
|
|
MemoryManager *memoryManager;
|
|
|
|
ExecutableAllocator *executableAllocator;
|
|
|
|
ExecutableAllocator *regExpAllocator;
|
2014-02-14 12:58:40 +00:00
|
|
|
QScopedPointer<EvalISelFactory> iselFactory;
|
2014-02-05 15:12:16 +00:00
|
|
|
|
2015-08-24 14:18:11 +00:00
|
|
|
ExecutionContext *currentContext;
|
2014-02-05 15:12:16 +00:00
|
|
|
|
2014-01-24 21:55:39 +00:00
|
|
|
Value *jsStackLimit;
|
2013-11-11 10:22:24 +00:00
|
|
|
|
2015-10-09 06:58:36 +00:00
|
|
|
Runtime runtime;
|
|
|
|
|
2013-04-19 09:47:50 +00:00
|
|
|
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
|
2012-11-18 22:33:06 +00:00
|
|
|
|
2013-11-11 10:22:24 +00:00
|
|
|
enum { JSStackLimit = 4*1024*1024 };
|
2013-09-03 10:40:07 +00:00
|
|
|
WTF::PageAllocation *jsStack;
|
2014-01-24 21:55:39 +00:00
|
|
|
Value *jsStackBase;
|
2013-09-03 10:40:07 +00:00
|
|
|
|
2014-11-01 22:04:20 +00:00
|
|
|
void pushForGC(Heap::Base *m) {
|
2014-11-12 15:07:56 +00:00
|
|
|
*jsStackTop = m;
|
2013-11-02 15:30:26 +00:00
|
|
|
++jsStackTop;
|
|
|
|
}
|
2014-11-01 22:04:20 +00:00
|
|
|
Heap::Base *popForGC() {
|
2013-11-02 15:30:26 +00:00
|
|
|
--jsStackTop;
|
2014-11-01 19:56:47 +00:00
|
|
|
return jsStackTop->heapObject();
|
2013-11-02 15:30:26 +00:00
|
|
|
}
|
2016-11-25 10:24:25 +00:00
|
|
|
|
|
|
|
QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) {
|
2015-03-13 16:21:18 +00:00
|
|
|
Value *ptr = jsStackTop;
|
|
|
|
jsStackTop = ptr + nValues;
|
2016-11-09 09:49:24 +00:00
|
|
|
for (int i = 0; i < nValues; ++i)
|
|
|
|
ptr[i] = Primitive::undefinedValue();
|
2015-03-13 16:21:18 +00:00
|
|
|
return ptr;
|
|
|
|
}
|
2013-11-02 15:30:26 +00:00
|
|
|
|
2013-06-27 06:57:47 +00:00
|
|
|
IdentifierTable *identifierTable;
|
2013-01-30 13:56:40 +00:00
|
|
|
|
2015-03-13 16:21:18 +00:00
|
|
|
Object *globalObject;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
Function *globalCode;
|
2013-01-28 15:46:09 +00:00
|
|
|
|
2016-03-23 12:17:10 +00:00
|
|
|
#ifdef V4_BOOTSTRAP
|
2014-12-30 14:31:09 +00:00
|
|
|
QJSEngine *jsEngine() const;
|
2014-12-30 15:38:20 +00:00
|
|
|
QQmlEngine *qmlEngine() const;
|
2016-03-23 12:17:10 +00:00
|
|
|
#else // !V4_BOOTSTRAP
|
|
|
|
QJSEngine *jsEngine() const { return v8Engine->publicEngine(); }
|
2016-10-22 03:24:20 +00:00
|
|
|
QQmlEngine *qmlEngine() const { return v8Engine ? v8Engine->engine() : nullptr; }
|
2016-03-23 12:17:10 +00:00
|
|
|
#endif // V4_BOOTSTRAP
|
2013-06-04 14:00:13 +00:00
|
|
|
QV8Engine *v8Engine;
|
2013-04-17 16:17:30 +00:00
|
|
|
|
2015-03-25 12:49:51 +00:00
|
|
|
enum JSObjects {
|
2015-08-24 14:24:34 +00:00
|
|
|
RootContext,
|
2015-08-24 13:31:46 +00:00
|
|
|
IntegerNull, // Has to come after the RootContext to make the context stack safe
|
2015-03-25 12:49:51 +00:00
|
|
|
ObjectProto,
|
2015-03-25 13:40:35 +00:00
|
|
|
ArrayProto,
|
2017-02-20 12:27:22 +00:00
|
|
|
PropertyListProto,
|
2015-03-25 13:40:35 +00:00
|
|
|
StringProto,
|
|
|
|
NumberProto,
|
|
|
|
BooleanProto,
|
|
|
|
DateProto,
|
|
|
|
FunctionProto,
|
|
|
|
RegExpProto,
|
|
|
|
ErrorProto,
|
|
|
|
EvalErrorProto,
|
|
|
|
RangeErrorProto,
|
|
|
|
ReferenceErrorProto,
|
|
|
|
SyntaxErrorProto,
|
|
|
|
TypeErrorProto,
|
|
|
|
URIErrorProto,
|
|
|
|
VariantProto,
|
|
|
|
SequenceProto,
|
2015-03-25 20:06:18 +00:00
|
|
|
ArrayBufferProto,
|
|
|
|
DataViewProto,
|
2015-04-26 12:24:08 +00:00
|
|
|
ValueTypeProto,
|
2015-09-09 13:23:18 +00:00
|
|
|
SignalHandlerProto,
|
2015-03-25 20:06:18 +00:00
|
|
|
|
|
|
|
Object_Ctor,
|
|
|
|
String_Ctor,
|
|
|
|
Number_Ctor,
|
|
|
|
Boolean_Ctor,
|
|
|
|
Array_Ctor,
|
|
|
|
Function_Ctor,
|
|
|
|
Date_Ctor,
|
|
|
|
RegExp_Ctor,
|
|
|
|
Error_Ctor,
|
|
|
|
EvalError_Ctor,
|
|
|
|
RangeError_Ctor,
|
|
|
|
ReferenceError_Ctor,
|
|
|
|
SyntaxError_Ctor,
|
|
|
|
TypeError_Ctor,
|
|
|
|
URIError_Ctor,
|
|
|
|
ArrayBuffer_Ctor,
|
|
|
|
DataView_Ctor,
|
2015-03-25 20:31:16 +00:00
|
|
|
|
|
|
|
Eval_Function,
|
2015-08-27 20:47:23 +00:00
|
|
|
GetStack_Function,
|
2015-03-25 20:31:16 +00:00
|
|
|
ThrowerObject,
|
2015-03-25 12:49:51 +00:00
|
|
|
NJSObjects
|
|
|
|
};
|
|
|
|
Value *jsObjects;
|
2015-03-25 20:06:18 +00:00
|
|
|
enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
|
|
|
|
|
2015-08-24 14:24:34 +00:00
|
|
|
GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContext); }
|
2015-03-25 20:06:18 +00:00
|
|
|
FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); }
|
|
|
|
FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); }
|
|
|
|
FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); }
|
|
|
|
FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
|
|
|
|
FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
|
|
|
|
FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
|
|
|
|
FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
|
|
|
|
FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
|
|
|
|
FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
|
|
|
|
FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
|
|
|
|
FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
|
|
|
|
FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
|
|
|
|
FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
|
|
|
|
FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
|
|
|
|
FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
|
|
|
|
FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
|
|
|
|
FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
|
|
|
|
FunctionObject *typedArrayCtors;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2015-03-25 13:40:35 +00:00
|
|
|
Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
|
|
|
|
Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
|
2017-02-20 12:27:22 +00:00
|
|
|
Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); }
|
2015-03-25 13:40:35 +00:00
|
|
|
Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
|
|
|
|
Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
|
|
|
|
Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
|
|
|
|
Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
|
|
|
|
Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
|
|
|
|
Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
|
|
|
|
Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
|
|
|
|
Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
|
|
|
|
Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
|
|
|
|
Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
|
|
|
|
Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
|
|
|
|
Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
|
|
|
|
Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
|
|
|
|
Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
|
|
|
|
Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
|
2014-11-24 14:38:41 +00:00
|
|
|
|
2015-03-25 20:06:18 +00:00
|
|
|
Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
|
|
|
|
Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
|
|
|
|
Object *typedArrayPrototype;
|
2014-11-24 14:38:41 +00:00
|
|
|
|
2015-04-26 12:24:08 +00:00
|
|
|
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
|
2015-09-09 13:23:18 +00:00
|
|
|
Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
|
2015-04-26 12:24:08 +00:00
|
|
|
|
2014-04-16 07:36:38 +00:00
|
|
|
InternalClassPool *classPool;
|
2013-03-04 10:48:49 +00:00
|
|
|
InternalClass *emptyClass;
|
2013-11-21 13:26:08 +00:00
|
|
|
|
2013-03-04 10:48:49 +00:00
|
|
|
InternalClass *arrayClass;
|
2015-08-27 10:17:21 +00:00
|
|
|
InternalClass *stringClass;
|
2013-09-01 19:22:57 +00:00
|
|
|
|
2013-08-29 19:23:04 +00:00
|
|
|
InternalClass *functionClass;
|
2016-12-09 09:47:57 +00:00
|
|
|
InternalClass *scriptFunctionClass;
|
2013-09-01 19:22:57 +00:00
|
|
|
InternalClass *protoClass;
|
|
|
|
|
2013-09-02 12:25:15 +00:00
|
|
|
InternalClass *regExpExecArrayClass;
|
2015-08-27 12:38:24 +00:00
|
|
|
InternalClass *regExpObjectClass;
|
2015-01-10 19:35:18 +00:00
|
|
|
|
2013-08-16 06:53:47 +00:00
|
|
|
InternalClass *argumentsObjectClass;
|
|
|
|
InternalClass *strictArgumentsObjectClass;
|
2013-03-04 10:48:49 +00:00
|
|
|
|
2015-08-27 20:47:23 +00:00
|
|
|
InternalClass *errorClass;
|
2015-09-01 11:46:46 +00:00
|
|
|
InternalClass *errorClassWithMessage;
|
|
|
|
InternalClass *errorProtoClass;
|
2015-08-27 20:47:23 +00:00
|
|
|
|
2015-03-25 20:31:16 +00:00
|
|
|
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
|
2015-08-27 20:47:23 +00:00
|
|
|
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
|
2015-03-25 20:31:16 +00:00
|
|
|
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
|
2013-01-23 09:07:18 +00:00
|
|
|
|
2014-03-10 14:18:54 +00:00
|
|
|
Property *argumentsAccessors;
|
|
|
|
int nArgumentsAccessors;
|
2013-01-18 11:47:43 +00:00
|
|
|
|
2015-04-26 07:22:17 +00:00
|
|
|
enum JSStrings {
|
|
|
|
String_Empty,
|
|
|
|
String_undefined,
|
|
|
|
String_null,
|
|
|
|
String_true,
|
|
|
|
String_false,
|
|
|
|
String_boolean,
|
|
|
|
String_number,
|
|
|
|
String_string,
|
|
|
|
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_destroy,
|
|
|
|
String_valueOf,
|
|
|
|
String_byteLength,
|
|
|
|
String_byteOffset,
|
|
|
|
String_buffer,
|
|
|
|
String_lastIndex,
|
|
|
|
NJSStrings
|
|
|
|
};
|
|
|
|
Value *jsStrings;
|
|
|
|
|
|
|
|
String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
|
|
|
|
String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
|
|
|
|
String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
|
|
|
|
String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
|
|
|
|
String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
|
|
|
|
String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
|
|
|
|
String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
|
|
|
|
String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
|
|
|
|
String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
|
|
|
|
String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
|
|
|
|
String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
|
|
|
|
String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
|
|
|
|
String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
|
|
|
|
String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
|
|
|
|
String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
|
|
|
|
String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
|
|
|
|
String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
|
|
|
|
String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
|
|
|
|
String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
|
|
|
|
String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
|
|
|
|
String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
|
|
|
|
String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
|
|
|
|
String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
|
|
|
|
String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
|
|
|
|
String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
|
|
|
|
String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
|
|
|
|
String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
|
|
|
|
String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
|
|
|
|
String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
|
|
|
|
String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
|
|
|
|
String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
|
|
|
|
String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
|
|
|
|
String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
|
|
|
|
String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
|
|
|
|
String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
|
|
|
|
String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-08-15 12:11:19 +00:00
|
|
|
QSet<CompiledData::CompilationUnit*> compilationUnits;
|
2012-11-28 12:39:14 +00:00
|
|
|
|
2013-06-04 08:05:51 +00:00
|
|
|
quint32 m_engineId;
|
|
|
|
|
2013-03-30 16:43:03 +00:00
|
|
|
RegExpCache *regExpCache;
|
|
|
|
|
2013-05-14 00:01:04 +00:00
|
|
|
// 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:
|
2014-04-29 14:46:12 +00:00
|
|
|
ScarceResourceData(const QVariant &data = QVariant()) : data(data) {}
|
2013-05-14 00:01:04 +00:00
|
|
|
QVariant data;
|
|
|
|
QIntrusiveListNode node;
|
|
|
|
};
|
|
|
|
QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
|
|
|
|
|
2013-06-04 12:28:13 +00:00
|
|
|
// 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;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
ExecutionEngine(EvalISelFactory *iselFactory = 0);
|
2012-12-04 10:30:26 +00:00
|
|
|
~ExecutionEngine();
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2016-07-28 08:21:06 +00:00
|
|
|
#ifdef QT_NO_QML_DEBUGGER
|
|
|
|
QV4::Debugging::Debugger *debugger() const { return nullptr; }
|
|
|
|
QV4::Profiling::Profiler *profiler() const { return nullptr; }
|
|
|
|
|
|
|
|
void setDebugger(Debugging::Debugger *) {}
|
|
|
|
void setProfiler(Profiling::Profiler *) {}
|
|
|
|
#else
|
2016-07-25 15:02:45 +00:00
|
|
|
QV4::Debugging::Debugger *debugger() const { return m_debugger; }
|
|
|
|
QV4::Profiling::Profiler *profiler() const { return m_profiler; }
|
|
|
|
|
2015-10-13 14:58:04 +00:00
|
|
|
void setDebugger(Debugging::Debugger *debugger);
|
2016-07-20 13:38:08 +00:00
|
|
|
void setProfiler(Profiling::Profiler *profiler);
|
2016-07-28 08:21:06 +00:00
|
|
|
#endif // QT_NO_QML_DEBUGGER
|
2013-07-24 08:29:04 +00:00
|
|
|
|
2015-08-24 14:16:56 +00:00
|
|
|
ExecutionContext *pushGlobalContext();
|
2015-08-21 12:55:53 +00:00
|
|
|
void pushContext(Heap::ExecutionContext *context);
|
2015-08-24 14:16:56 +00:00
|
|
|
void pushContext(ExecutionContext *context);
|
|
|
|
void popContext();
|
2015-08-24 13:31:46 +00:00
|
|
|
ExecutionContext *parentContext(ExecutionContext *context) const;
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::Object *newObject();
|
2014-11-24 14:38:41 +00:00
|
|
|
Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2014-11-28 08:20:29 +00:00
|
|
|
Heap::String *newString(const QString &s = QString());
|
2014-11-11 14:08:30 +00:00
|
|
|
Heap::String *newIdentifier(const QString &text);
|
2013-01-30 13:56:40 +00:00
|
|
|
|
2015-04-30 22:08:55 +00:00
|
|
|
Heap::Object *newStringObject(const String *string);
|
2015-01-16 11:44:51 +00:00
|
|
|
Heap::Object *newNumberObject(double value);
|
2015-01-15 20:54:12 +00:00
|
|
|
Heap::Object *newBooleanObject(bool b);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::ArrayObject *newArrayObject(int count = 0);
|
2015-09-08 12:58:16 +00:00
|
|
|
Heap::ArrayObject *newArrayObject(const Value *values, int length);
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::ArrayObject *newArrayObject(const QStringList &list);
|
2014-11-24 14:38:41 +00:00
|
|
|
Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2015-03-04 19:57:14 +00:00
|
|
|
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
|
2015-08-27 10:17:21 +00:00
|
|
|
Heap::ArrayBuffer *newArrayBuffer(size_t length);
|
2015-03-04 19:57:14 +00:00
|
|
|
|
2015-01-15 10:36:57 +00:00
|
|
|
Heap::DateObject *newDateObject(const Value &value);
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::DateObject *newDateObject(const QDateTime &dt);
|
V4: Handle QTime->DateObject conversion better
By specification, date conversion functions for dates before the epoch
are not DST corrected. We converted QTime to a QDateTime where we set
the date part to Jan. 1, 1970, and then convert that to msecs since the
epoch UTC. For places on Earth where they had DST on that day (e.g.
Hobart in Australia), strange things happen: conversion from a QTime to
DateObject will use DST (because it's after the epoch in local time),
but conversions from DateObject to QTime won't use the DST because it's
before the epoch (in UTC).
Now as everyone knows, a 24-hour clock time has no meaning without a
date, only "elapsed time" has. But users still expect to be able to pass
QTime to QML/JS. So, we do the conversion on day 0 of month 0 of year 0,
and all of it in local time. This gives a stable conversion in both
directions, and the values in both C++ and QML/JS are the same for any
timezone (with or without DST) on this planet.
Task-number: QTBUG-54378
Change-Id: I892e16a93f015e92d311c6cae3ae7768b7373f6a
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
2016-07-08 14:40:28 +00:00
|
|
|
Heap::DateObject *newDateObjectFromTime(const QTime &t);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
|
|
|
|
Heap::RegExpObject *newRegExpObject(RegExp *re, bool global);
|
|
|
|
Heap::RegExpObject *newRegExpObject(const QRegExp &re);
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2015-01-15 10:36:57 +00:00
|
|
|
Heap::Object *newErrorObject(const Value &value);
|
2014-11-11 12:34:18 +00:00
|
|
|
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);
|
2015-09-01 11:46:46 +00:00
|
|
|
Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column);
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::Object *newTypeErrorObject(const QString &message);
|
|
|
|
Heap::Object *newRangeErrorObject(const QString &message);
|
2015-01-15 10:36:57 +00:00
|
|
|
Heap::Object *newURIErrorObject(const Value &message);
|
2012-12-04 18:50:25 +00:00
|
|
|
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::Object *newVariantObject(const QVariant &v);
|
2013-05-14 00:01:04 +00:00
|
|
|
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::Object *newForEachIteratorObject(Object *o);
|
2013-01-18 11:47:43 +00:00
|
|
|
|
2015-06-18 11:12:31 +00:00
|
|
|
Heap::QmlContext *qmlContext() const;
|
2015-06-15 14:41:24 +00:00
|
|
|
QObject *qmlScopeObject() const;
|
2015-08-12 12:14:40 +00:00
|
|
|
ReturnedValue qmlSingletonWrapper(String *name);
|
2015-06-15 14:41:24 +00:00
|
|
|
QQmlContextData *callingQmlContext() const;
|
|
|
|
|
2013-05-03 14:51:32 +00:00
|
|
|
|
2013-05-25 13:31:23 +00:00
|
|
|
StackTrace stackTrace(int frameLimit = -1) const;
|
2013-05-22 08:47:36 +00:00
|
|
|
StackFrame currentStackFrame() const;
|
2013-05-29 07:59:40 +00:00
|
|
|
QUrl resolvedUrl(const QString &file);
|
2013-05-22 08:47:36 +00:00
|
|
|
|
2013-01-18 11:47:43 +00:00
|
|
|
void requireArgumentsAccessors(int n);
|
2013-01-28 15:46:09 +00:00
|
|
|
|
|
|
|
void markObjects();
|
2013-03-05 15:11:22 +00:00
|
|
|
|
2013-03-14 13:03:04 +00:00
|
|
|
void initRootContext();
|
2013-05-06 11:29:24 +00:00
|
|
|
|
|
|
|
InternalClass *newClass(const InternalClass &other);
|
2013-05-25 13:31:23 +00:00
|
|
|
|
2013-10-01 14:19:28 +00:00
|
|
|
// Exception handling
|
2015-03-13 16:21:18 +00:00
|
|
|
Value *exceptionValue;
|
2013-10-01 14:19:28 +00:00
|
|
|
StackTrace exceptionStackTrace;
|
|
|
|
|
2015-01-15 10:36:57 +00:00
|
|
|
ReturnedValue throwError(const Value &value);
|
2014-11-12 12:55:55 +00:00
|
|
|
ReturnedValue catchException(StackTrace *trace = 0);
|
2013-10-01 14:19:28 +00:00
|
|
|
|
2014-07-28 08:07:57 +00:00
|
|
|
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);
|
2015-01-15 10:36:57 +00:00
|
|
|
ReturnedValue throwReferenceError(const Value &value);
|
2014-07-28 08:07:57 +00:00
|
|
|
ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
|
2015-01-15 10:36:57 +00:00
|
|
|
ReturnedValue throwRangeError(const Value &value);
|
2014-07-28 08:07:57 +00:00
|
|
|
ReturnedValue throwRangeError(const QString &message);
|
2015-01-15 10:36:57 +00:00
|
|
|
ReturnedValue throwURIError(const Value &msg);
|
2014-07-28 08:07:57 +00:00
|
|
|
ReturnedValue throwUnimplemented(const QString &message);
|
|
|
|
|
2013-10-17 06:56:51 +00:00
|
|
|
// Use only inside catch(...) -- will re-throw if no JS exception
|
2014-11-12 12:55:55 +00:00
|
|
|
QQmlError catchExceptionAsQmlError();
|
2013-10-17 06:56:51 +00:00
|
|
|
|
2015-01-02 13:37:26 +00:00
|
|
|
// variant conversions
|
2015-01-15 10:36:57 +00:00
|
|
|
QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
|
2015-01-02 14:07:35 +00:00
|
|
|
QV4::ReturnedValue fromVariant(const QVariant &);
|
2015-01-02 13:37:26 +00:00
|
|
|
|
2015-04-26 20:58:49 +00:00
|
|
|
QVariantMap variantMapFromJS(const QV4::Object *o);
|
2015-01-02 13:37:26 +00:00
|
|
|
|
2015-04-26 20:58:49 +00:00
|
|
|
bool metaTypeFromJS(const Value *value, int type, void *data);
|
2015-01-02 14:07:35 +00:00
|
|
|
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
|
2015-01-02 13:37:26 +00:00
|
|
|
|
2015-06-04 08:24:46 +00:00
|
|
|
void assertObjectBelongsToEngine(const Heap::Base &baseObject);
|
2016-04-25 13:01:04 +00:00
|
|
|
|
2016-06-22 08:12:13 +00:00
|
|
|
bool checkStackLimits(Scope &scope);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void failStackLimitCheck(Scope &scope);
|
2016-07-25 15:02:45 +00:00
|
|
|
|
2016-07-28 08:21:06 +00:00
|
|
|
#ifndef QT_NO_QML_DEBUGGER
|
2016-07-25 15:02:45 +00:00
|
|
|
QV4::Debugging::Debugger *m_debugger;
|
|
|
|
QV4::Profiling::Profiler *m_profiler;
|
2016-07-28 08:21:06 +00:00
|
|
|
#endif
|
2013-03-05 15:11:22 +00:00
|
|
|
};
|
|
|
|
|
2015-10-08 10:59:40 +00:00
|
|
|
// 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.
|
2016-05-23 14:11:50 +00:00
|
|
|
#ifndef V4_BOOTSTRAP
|
2015-10-08 10:59:40 +00:00
|
|
|
struct NoThrowEngine : public ExecutionEngine
|
|
|
|
{
|
|
|
|
};
|
2016-05-23 14:11:50 +00:00
|
|
|
#else
|
|
|
|
struct NoThrowEngine;
|
|
|
|
#endif
|
2015-10-08 10:59:40 +00:00
|
|
|
|
|
|
|
|
2015-08-21 12:55:53 +00:00
|
|
|
inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
|
|
|
|
{
|
2015-08-24 14:18:11 +00:00
|
|
|
Q_ASSERT(currentContext && context);
|
2015-08-24 13:31:46 +00:00
|
|
|
Value *v = jsAlloca(2);
|
|
|
|
v[0] = Encode(context);
|
2015-08-24 14:18:11 +00:00
|
|
|
v[1] = Encode((int)(v - static_cast<Value *>(currentContext)));
|
|
|
|
currentContext = static_cast<ExecutionContext *>(v);
|
|
|
|
current = currentContext->d();
|
2015-08-21 12:55:53 +00:00
|
|
|
}
|
|
|
|
|
2015-08-24 14:16:56 +00:00
|
|
|
inline void ExecutionEngine::pushContext(ExecutionContext *context)
|
2014-11-18 16:35:48 +00:00
|
|
|
{
|
2015-08-21 12:55:53 +00:00
|
|
|
pushContext(context->d());
|
2014-11-18 16:35:48 +00:00
|
|
|
}
|
|
|
|
|
2015-08-21 12:55:53 +00:00
|
|
|
|
2015-08-24 14:16:56 +00:00
|
|
|
inline void ExecutionEngine::popContext()
|
2014-11-18 16:35:48 +00:00
|
|
|
{
|
2015-08-24 14:18:11 +00:00
|
|
|
Q_ASSERT(jsStackTop > currentContext);
|
|
|
|
QV4::Value *offset = (currentContext + 1);
|
2015-08-24 13:31:46 +00:00
|
|
|
Q_ASSERT(offset->isInteger());
|
|
|
|
int o = offset->integerValue();
|
|
|
|
Q_ASSERT(o);
|
2015-08-24 14:18:11 +00:00
|
|
|
currentContext -= o;
|
|
|
|
current = currentContext->d();
|
2014-11-18 16:35:48 +00:00
|
|
|
}
|
|
|
|
|
2016-03-23 12:23:21 +00:00
|
|
|
inline ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) const
|
|
|
|
{
|
|
|
|
Value *offset = static_cast<Value *>(context) + 1;
|
|
|
|
Q_ASSERT(offset->isInteger());
|
|
|
|
int o = offset->integerValue();
|
|
|
|
return o ? context - o : 0;
|
|
|
|
}
|
|
|
|
|
2014-11-01 19:56:47 +00:00
|
|
|
inline
|
2014-11-01 22:04:20 +00:00
|
|
|
void Heap::Base::mark(QV4::ExecutionEngine *engine)
|
2014-11-01 19:56:47 +00:00
|
|
|
{
|
2015-01-09 18:48:56 +00:00
|
|
|
Q_ASSERT(inUse());
|
2015-01-09 21:02:40 +00:00
|
|
|
if (isMarked())
|
2014-11-01 19:56:47 +00:00
|
|
|
return;
|
2015-05-08 10:34:53 +00:00
|
|
|
#ifndef QT_NO_DEBUG
|
|
|
|
engine->assertObjectBelongsToEngine(*this);
|
|
|
|
#endif
|
2015-01-09 21:02:40 +00:00
|
|
|
setMarkBit();
|
2013-11-02 15:30:26 +00:00
|
|
|
engine->pushForGC(this);
|
|
|
|
}
|
|
|
|
|
2015-02-13 14:31:23 +00:00
|
|
|
inline void Value::mark(ExecutionEngine *e)
|
|
|
|
{
|
2015-09-08 12:58:55 +00:00
|
|
|
Heap::Base *o = heapObject();
|
|
|
|
if (o)
|
|
|
|
o->mark(e);
|
2015-02-13 14:31:23 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 08:12:13 +00:00
|
|
|
#define CHECK_STACK_LIMITS(v4, scope) if ((v4)->checkStackLimits(scope)) return; \
|
2016-04-25 13:01:04 +00:00
|
|
|
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
|
2013-11-02 15:30:26 +00:00
|
|
|
|
2016-04-25 13:01:04 +00:00
|
|
|
struct ExecutionEngineCallDepthRecorder
|
|
|
|
{
|
|
|
|
ExecutionEngine *ee;
|
2013-11-02 15:30:26 +00:00
|
|
|
|
2016-04-25 13:01:04 +00:00
|
|
|
ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
|
|
|
|
~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
|
|
|
|
};
|
|
|
|
|
2016-06-22 08:12:13 +00:00
|
|
|
inline bool ExecutionEngine::checkStackLimits(Scope &scope)
|
2016-04-25 13:01:04 +00:00
|
|
|
{
|
|
|
|
if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
|
2016-06-22 08:12:13 +00:00
|
|
|
failStackLimitCheck(scope);
|
2016-04-25 13:01:04 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2013-11-02 15:30:26 +00:00
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
} // namespace QV4
|
2012-11-17 20:54:26 +00:00
|
|
|
|
2013-01-31 09:00:06 +00:00
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
2013-03-18 10:03:51 +00:00
|
|
|
#endif // QV4ENGINE_H
|