aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-09-25 20:56:51 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-09-25 20:56:51 +0200
commitf9ef039ad955db67dc3ab6e9056afc4a325aa9a3 (patch)
tree4928ff85fb630639e306ea4eb7137a2064a80c8b /src/qml
parent0238c739f81911f0963cf2c40b27dcfc8e3d38b7 (diff)
parent52fb4685e95e5b44e54d2d0f8ea27dea866c75e9 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts: src/qml/debugger/qqmldebug.cpp Change-Id: I93de5a81b18cdece475870cf7cfba1b9baef2304
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp25
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h7
-rw-r--r--src/qml/compiler/qv4ssa.cpp2
-rw-r--r--src/qml/debugger/qqmldebug.cpp2
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp6
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc2
-rw-r--r--src/qml/jsapi/qjsengine.cpp9
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp31
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp12
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h5
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp13
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h37
-rw-r--r--src/qml/jsruntime/qv4context.cpp71
-rw-r--r--src/qml/jsruntime/qv4context_p.h26
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp31
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h3
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp25
-rw-r--r--src/qml/jsruntime/qv4engine.cpp305
-rw-r--r--src/qml/jsruntime/qv4engine_p.h78
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp165
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h91
-rw-r--r--src/qml/jsruntime/qv4function.cpp31
-rw-r--r--src/qml/jsruntime/qv4function_p.h7
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp127
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h17
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp16
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h2
-rw-r--r--src/qml/jsruntime/qv4include.cpp23
-rw-r--r--src/qml/jsruntime/qv4include_p.h6
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp87
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h1
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp92
-rw-r--r--src/qml/jsruntime/qv4managed.cpp24
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp5
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp239
-rw-r--r--src/qml/jsruntime/qv4object_p.h113
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp4
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h7
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp12
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp119
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h11
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp79
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h29
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp119
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h83
-rw-r--r--src/qml/jsruntime/qv4script.cpp95
-rw-r--r--src/qml/jsruntime/qv4script_p.h30
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp23
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp11
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp24
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp26
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h11
-rw-r--r--src/qml/jsruntime/qv4value_p.h4
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp9
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h7
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp14
-rw-r--r--src/qml/memory/qv4mm.cpp68
-rw-r--r--src/qml/memory/qv4mm_p.h167
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp17
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp13
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp31
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h18
-rw-r--r--src/qml/qml/qqmlexpression.cpp2
-rw-r--r--src/qml/qml/qqmlimport.cpp33
-rw-r--r--src/qml/qml/qqmlinfo.cpp28
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp8
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp9
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h2
-rw-r--r--src/qml/qml/qqmllocale.cpp2
-rw-r--r--src/qml/qml/qqmllocale_p.h7
-rw-r--r--src/qml/qml/qqmlmetatype.cpp77
-rw-r--r--src/qml/qml/qqmlmetatype_p.h10
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp15
-rw-r--r--src/qml/qml/qqmlproperty.cpp8
-rw-r--r--src/qml/qml/qqmltypeloader.cpp23
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp14
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp32
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h3
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp49
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp30
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp62
-rw-r--r--src/qml/qml/v8/qv8engine_p.h4
-rw-r--r--src/qml/types/qqmlbind.cpp36
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp26
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h7
-rw-r--r--src/qml/types/qqmlitemselectionmodel.qdoc2
-rw-r--r--src/qml/types/qqmllistmodel.cpp26
-rw-r--r--src/qml/types/qqmllistmodel_p.h1
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h4
-rw-r--r--src/qml/types/qquickworkerscript.cpp26
-rw-r--r--src/qml/util/qqmladaptormodel.cpp10
-rw-r--r--src/qml/util/qqmllistcompositor_p.h12
-rw-r--r--src/qml/util/qqmlpropertymap.cpp3
109 files changed, 1799 insertions, 1602 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 4b1e3601dc..7b0d4240c4 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1590,7 +1590,7 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
if (member->name->constData()->isUpper()) {
bool ok = false;
- int value = type->enumValue(*member->name, &ok);
+ int value = type->enumValue(qmlEngine, *member->name, &ok);
if (ok) {
member->setEnumValue(value);
resolver->clear();
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 80ffafda72..e36ba76326 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1163,8 +1163,6 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
if (!type && typeName != QLatin1String("Qt"))
return true;
- if (type && type->isComposite()) //No enums on composite (or composite singleton) types
- return true;
int value = 0;
bool ok = false;
@@ -1182,7 +1180,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
} else {
// Otherwise we have to search the whole type
if (type) {
- value = type->enumValue(QHashedStringRef(enumValue), &ok);
+ value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
} else {
QByteArray enumName = enumValue.toUtf8();
const QMetaObject *metaObject = StaticQtMetaObject::get();
@@ -1210,7 +1208,9 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QByteArray &e
if (scope != QLatin1String("Qt")) {
QQmlType *type = 0;
imports->resolveType(scope, &type, 0, 0, 0);
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ if (!type)
+ return -1;
+ return type ? type->enumValue(compiler->enginePrivate(), QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
}
const QMetaObject *mo = StaticQtMetaObject::get();
@@ -1719,17 +1719,6 @@ const QQmlImports &QQmlPropertyValidator::imports() const
return *compiler->imports();
}
-QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const
-{
- const QmlIR::Object *object = compiler->qmlObjects()->value(objectIndex);
- if (!object)
- return QString();
- int reverseIndex = object->runtimeFunctionIndices->indexOf(binding->value.compiledScriptIndex);
- if (reverseIndex == -1)
- return QString();
- return compiler->bindingAsString(object, reverseIndex);
-}
-
typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector;
struct BindingFinder
@@ -1998,10 +1987,12 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
- customParser->compiler = this;
+ customParser->validator = this;
+ customParser->engine = enginePrivate;
customParser->imports = compiler->imports();
customParser->verifyBindings(qmlUnit, customBindings);
- customParser->compiler = 0;
+ customParser->validator = 0;
+ customParser->engine = 0;
customParser->imports = (QQmlImports*)0;
customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 75987af656..09ef7aad67 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -264,7 +264,7 @@ protected:
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
};
-class QQmlPropertyValidator : public QQmlCompilePass, public QQmlCustomParserCompilerBackend
+class QQmlPropertyValidator : public QQmlCompilePass
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
@@ -272,9 +272,8 @@ public:
bool validate();
- // Re-implemented for QQmlCustomParser
- virtual const QQmlImports &imports() const;
- virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
+ const QQmlImports &imports() const;
+ QQmlEnginePrivate *engine() const { return enginePrivate; }
private:
bool validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty = false) const;
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index c150666a11..32169f3352 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -3504,7 +3504,7 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
}
#endif
-void cleanupBasicBlocks(IR::Function *function)
+static void cleanupBasicBlocks(IR::Function *function)
{
showMeTheCode(function, "Before basic block cleanup");
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 64004fc86a..b308f5aa29 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -147,6 +147,8 @@ bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const Q
}
/*!
+ * \since 5.6
+ *
* Enables debugging for QML engines created after calling this function. The debug connector will
* connect to a debugger waiting on a local socket at the given \a socketFileName and block the QML
* engine until the connection is established if \a mode is \c WaitForClient. If \a mode is not
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
index 8de734fa68..460cb8f203 100644
--- a/src/qml/debugger/qqmldebugconnector.cpp
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -107,9 +107,9 @@ QQmlDebugConnector *QQmlDebugConnector::instance()
if (!QQmlEnginePrivate::qml_debugging_enabled) {
if (!params->arguments.isEmpty()) {
- qWarning() << QString::fromLatin1(
- "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging has not "
- "been enabled.").arg(params->arguments);
+ qWarning().noquote() << QString::fromLatin1(
+ "QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging "
+ "has not been enabled.").arg(params->arguments);
params->arguments.clear();
}
return 0;
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc
index 54ed3f1e6e..426848f6e6 100644
--- a/src/qml/doc/src/cppintegration/definetypes.qdoc
+++ b/src/qml/doc/src/cppintegration/definetypes.qdoc
@@ -314,7 +314,7 @@ merged with the original target class when used from within QML. For example:
The \c leftMargin property is a new property added to an existing C++ type, \l
QLineEdit, without modifying its source code.
-The \l qmlRegisterExtendedType() function is for registering extended types.
+The \l {QQmlEngine::}{qmlRegisterExtendedType()} function is for registering extended types.
Note that it has two forms.
\code
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 4910b6a1c6..b217d3fb4c 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -317,7 +317,9 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
{
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
- QV4::ScopedContext ctx(scope, v4->currentContext());
+ QV4::ExecutionContextSaver saver(scope);
+
+ QV4::ExecutionContext *ctx = v4->currentContext;
if (ctx->d() != v4->rootContext()->d())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@@ -330,8 +332,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
result = script.run();
if (scope.engine->hasException)
result = v4->catchException();
- if (ctx->d() != v4->rootContext()->d())
- v4->popContext();
+
return QJSValue(v4, result->asReturnedValue());
}
@@ -553,7 +554,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
Creates a QJSValue with the given \a value.
- \sa fromScriptValue(), newVariant()
+ \sa fromScriptValue()
*/
/*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 2f6cf40beb..698b4c325c 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -40,9 +40,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
- : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass,
- context->d()->engine->objectPrototype())
- , context(context->d())
+ : context(context->d())
, fullyCreated(false)
{
Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
@@ -56,20 +54,20 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
if (context->d()->strictMode) {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller()));
- args->propertyAt(CalleePropertyIndex)->value = v4->thrower();
- args->propertyAt(CalleePropertyIndex)->set = v4->thrower();
- args->propertyAt(CallerPropertyIndex)->value = v4->thrower();
- args->propertyAt(CallerPropertyIndex)->set = v4->thrower();
+ *args->propertyData(CalleePropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
+ *args->propertyData(CalleePropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
+ *args->propertyData(CallerPropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
+ *args->propertyData(CallerPropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
args->arrayReserve(context->argc());
args->arrayPut(0, context->args(), context->argc());
args->d()->fullyCreated = true;
} else {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
- args->memberData()->data[CalleePropertyIndex] = context->d()->function->asReturnedValue();
+ *args->propertyData(CalleePropertyIndex) = context->d()->function->asReturnedValue();
}
Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
- args->memberData()->data[LengthPropertyIndex] = Primitive::fromInt32(context->d()->callData->argc);
+ *args->propertyData(LengthPropertyIndex) = Primitive::fromInt32(context->d()->callData->argc);
}
void ArgumentsObject::fullyCreate()
@@ -84,10 +82,9 @@ void ArgumentsObject::fullyCreate()
Scope scope(engine());
Scoped<MemberData> md(scope, d()->mappedArguments);
- if (!md || md->size() < numAccessors)
- d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
+ d()->mappedArguments = md->allocate(engine(), numAccessors);
for (uint i = 0; i < numAccessors; ++i) {
- mappedArguments()->data[i] = context()->callData->args[i];
+ d()->mappedArguments->data[i] = context()->callData->args[i];
arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
}
arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors);
@@ -117,13 +114,13 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
map->copy(pd, mapAttrs);
setArrayAttributes(index, Attr_Data);
pd = arrayData()->getProperty(index);
- pd->value = mappedArguments()->data[index];
+ pd->value = d()->mappedArguments->data[index];
}
- bool strict = engine->currentContext()->strictMode;
- engine->currentContext()->strictMode = false;
+ bool strict = engine->current->strictMode;
+ engine->current->strictMode = false;
bool result = Object::defineOwnProperty2(scope.engine, index, desc, attrs);
- engine->currentContext()->strictMode = strict;
+ engine->current->strictMode = strict;
if (isMapped && attrs.isData()) {
Q_ASSERT(arrayData());
@@ -140,7 +137,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
}
}
- if (engine->currentContext()->strictMode && !result)
+ if (engine->current->strictMode && !result)
return engine->throwTypeError();
return result;
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index aab5e2c156..98a600fab6 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -103,7 +103,6 @@ struct ArgumentsObject: Object {
Heap::CallContext *context() const { return d()->context; }
bool fullyCreated() const { return d()->fullyCreated; }
- Heap::MemberData *mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
return m->d()->vtable()->type == Type_ArgumentsObject &&
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 23c9695cf4..0a3aa414de 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -58,7 +58,7 @@ ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData)
if (len != dl)
return v4->throwRangeError(QLatin1String("ArrayBuffer constructor: invalid length"));
- Scoped<ArrayBuffer> a(scope, v4->memoryManager->alloc<ArrayBuffer>(v4, len));
+ Scoped<ArrayBuffer> a(scope, v4->newArrayBuffer(len));
if (scope.engine->hasException)
return Encode::undefined();
return a.asReturnedValue();
@@ -83,22 +83,20 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
+Heap::ArrayBuffer::ArrayBuffer(size_t length)
{
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
data = 0;
- e->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
+ internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
return;
}
data->size = int(length);
memset(data->data(), 0, length + 1);
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype())
- , data(const_cast<QByteArray&>(array).data_ptr())
+Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array)
+ : data(const_cast<QByteArray&>(array).data_ptr())
{
data->ref.ref();
}
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index a7f9e92c80..19fd74465c 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -47,8 +47,8 @@ struct ArrayBufferCtor : FunctionObject {
};
struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object {
- ArrayBuffer(ExecutionEngine *e, size_t length);
- ArrayBuffer(ExecutionEngine *e, const QByteArray& array);
+ ArrayBuffer(size_t length);
+ ArrayBuffer(const QByteArray& array);
~ArrayBuffer();
QTypedArrayData<char> *data;
@@ -72,6 +72,7 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object
{
V4_OBJECT2(ArrayBuffer, Object)
V4_NEEDS_DESTROY
+ V4_PROTOTYPE(arrayBufferPrototype)
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index da91db6aae..ec0185de64 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -584,7 +584,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
ScopedValue v(scope);
for (const SparseArrayNode *it = os->sparse->begin();
it != os->sparse->end(); it = it->nextNode()) {
- v = otherObj->getValue(reinterpret_cast<Property *>(os->arrayData + it->value), other->d()->attrs[it->value]);
+ v = otherObj->getValue(os->arrayData[it->value], other->d()->attrs[it->value]);
obj->arraySet(oldSize + it->key(), v);
}
} else {
@@ -607,7 +607,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
return oldSize + n;
}
-Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
+void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor)
{
if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
@@ -622,7 +622,8 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
d->data(i) = Primitive::emptyValue();
d->len = index + 1;
}
- return reinterpret_cast<Property *>(d->arrayData + d->mappedIndex(index));
+ d->arrayData[d->mappedIndex(index)] = *v;
+ return;
}
}
@@ -632,7 +633,9 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
s = o->d()->arrayData.cast<Heap::SparseArrayData>();
- return reinterpret_cast<Property *>(s->arrayData + n->value);
+ s->arrayData[n->value] = *v;
+ if (isAccessor)
+ s->arrayData[n->value + Object::SetterOffset] = v[Object::SetterOffset];
}
@@ -769,7 +772,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
break;
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
- d->data(i) = thisObject->getValue(reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
+ d->data(i) = thisObject->getValue(sparse->arrayData()[n->value], a);
d->attrs[i] = a.isAccessor() ? Attr_Data : a;
n = n->nextNode();
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 729e657b1a..cca5bf7f20 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -101,7 +101,10 @@ struct ArrayData : public Base {
inline ReturnedValue get(uint i) const {
return vtable()->get(this, i);
}
+ inline void getProperty(uint index, Property *p, PropertyAttributes *attrs);
+ inline void setProperty(uint index, const Property *p);
inline Property *getProperty(uint index);
+ inline Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
inline PropertyAttributes attributes(uint i) const;
bool isEmpty(uint i) const {
@@ -205,7 +208,7 @@ struct Q_QML_EXPORT ArrayData : public Managed
static void sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint dataLen);
static uint append(Object *obj, ArrayObject *otherObj, uint n);
- static Property *insert(Object *o, uint index, bool isAccessor = false);
+ static void insert(Object *o, uint index, const Value *v, bool isAccessor = false);
};
struct Q_QML_EXPORT SimpleArrayData : public ArrayData
@@ -270,6 +273,25 @@ inline SparseArrayData::~SparseArrayData()
delete sparse;
}
+void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs)
+{
+ Property *pd = getProperty(index);
+ Q_ASSERT(pd);
+ *attrs = attributes(index);
+ p->value = pd->value;
+ if (attrs->isAccessor())
+ p->set = pd->set;
+}
+
+void ArrayData::setProperty(uint index, const Property *p)
+{
+ Property *pd = getProperty(index);
+ Q_ASSERT(pd);
+ pd->value = p->value;
+ if (attributes(index).isAccessor())
+ pd->set = p->set;
+}
+
inline Property *ArrayData::getProperty(uint index)
{
if (isSparse())
@@ -284,6 +306,19 @@ inline PropertyAttributes ArrayData::attributes(uint i) const
return static_cast<const SimpleArrayData *>(this)->attributes(i);
}
+Value *ArrayData::getValueOrSetter(uint index, PropertyAttributes *attrs)
+{
+ Property *p = getProperty(index);
+ if (!p) {
+ *attrs = Attr_Invalid;
+ return 0;
+ }
+
+ *attrs = attributes(index);
+ return attrs->isAccessor() ? &p->set : &p->value;
+}
+
+
}
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index f50c5ab017..403beacf39 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -83,21 +83,31 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi
return c;
}
-Heap::WithContext *ExecutionContext::newWithContext(Object *with)
+Heap::WithContext *ExecutionContext::newWithContext(Heap::Object *with)
{
- return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with);
+ return d()->engine->memoryManager->alloc<WithContext>(d(), with);
}
-Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const Value &exceptionValue)
+Heap::CatchContext *ExecutionContext::newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue)
{
- return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
+ Scope scope(this);
+ ScopedValue e(scope, exceptionValue);
+ return d()->engine->memoryManager->alloc<CatchContext>(d(), exceptionVarName, e);
}
Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
{
- return d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ Heap::QmlContext *c = d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ return c;
}
+Heap::QmlContext *ExecutionContext::newQmlContext(QQmlContextData *context, QObject *scopeObject)
+{
+ Scope scope(this);
+ Scoped<QmlContextWrapper> qml(scope, QmlContextWrapper::qmlScope(scope.engine, context, scopeObject));
+ Heap::QmlContext *c = d()->engine->memoryManager->alloc<QmlContext>(this, qml);
+ return c;
+}
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
@@ -142,38 +152,38 @@ Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
global = eng->globalObject->d();
}
-Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_WithContext)
+Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with)
+ : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_WithContext)
{
- callData = parent->callData;
- outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ outer = outerContext;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- withObject = with ? with->d() : 0;
+ withObject = with;
}
-Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_CatchContext)
+Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue)
+ : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_CatchContext)
{
- strictMode = parent->strictMode;
- callData = parent->callData;
- outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ outer = outerContext;
+ strictMode = outer->strictMode;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- this->exceptionVarName = exceptionVarName->d();
+ this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
}
-Heap::QmlContext::QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml)
- : Heap::ExecutionContext(outer->engine(), Heap::ExecutionContext::Type_QmlContext)
+Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml)
+ : Heap::ExecutionContext(outerContext->engine(), Heap::ExecutionContext::Type_QmlContext)
{
+ outer = outerContext->d();
strictMode = false;
- callData = parent->callData;
- this->outer = outer->d();
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
this->qml = qml->d();
}
@@ -362,7 +372,7 @@ void ExecutionContext::setProperty(String *name, const Value &value)
if (activation) {
uint member = activation->internalClass()->find(name);
if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
+ activation->putValue(member, value);
return;
}
}
@@ -538,7 +548,7 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
{
Scope scope(d()->engine);
ScopedContext it(scope, this->d());
- for (; it; it = it->d()->parent) {
+ for (; it; it = it->d()->outer) {
if (const CallContext *callCtx = it->asCallContext())
return callCtx->d()->function;
else if (it->asCatchContext() || it->asWithContext())
@@ -560,3 +570,8 @@ QQmlContextData *QmlContext::qmlContext() const
{
return d()->qml->context;
}
+
+void QmlContext::takeContextOwnership() {
+ d()->qml->ownsContext = true;
+}
+
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 2667bbe0b2..2807d1e29c 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -89,7 +89,6 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- Pointer<ExecutionContext> parent;
Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -99,6 +98,18 @@ struct ExecutionContext : Base {
int lineNumber;
};
+inline
+ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
+ : engine(engine)
+ , outer(0)
+ , lookups(0)
+ , compilationUnit(0)
+ , type(t)
+ , strictMode(false)
+ , lineNumber(-1)
+{}
+
+
struct CallContext : ExecutionContext {
CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
: ExecutionContext(engine, t)
@@ -119,20 +130,20 @@ struct GlobalContext : ExecutionContext {
};
struct CatchContext : ExecutionContext {
- CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue);
+ CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
- WithContext(ExecutionEngine *engine, QV4::Object *with);
+ WithContext(ExecutionContext *outerContext, Object *with);
Pointer<Object> withObject;
};
struct QmlContextWrapper;
struct QmlContext : ExecutionContext {
- QmlContext(QV4::ExecutionContext *outer, QV4::QmlContextWrapper *qml);
+ QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml);
Pointer<QmlContextWrapper> qml;
};
@@ -150,9 +161,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
- Heap::WithContext *newWithContext(Object *with);
- Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
+ Heap::WithContext *newWithContext(Heap::Object *with);
+ Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue);
Heap::QmlContext *newQmlContext(QmlContextWrapper *qml);
+ Heap::QmlContext *newQmlContext(QQmlContextData *context, QObject *scopeObject);
void createMutableBinding(String *name, bool deletable);
@@ -224,6 +236,8 @@ struct QmlContext : public ExecutionContext
QObject *qmlScope() const;
QQmlContextData *qmlContext() const;
+
+ void takeContextOwnership();
};
inline CallContext *ExecutionContext::asCallContext()
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index a741d61d10..8901834e76 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -62,7 +62,7 @@ ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData)
if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength)
return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range"));
- Scoped<DataView> a(scope, scope.engine->memoryManager->alloc<DataView>(scope.engine));
+ Scoped<DataView> a(scope, scope.engine->memoryManager->allocObject<DataView>());
a->d()->buffer = buffer->d();
a->d()->byteLength = byteLength;
a->d()->byteOffset = byteOffset;
@@ -76,15 +76,6 @@ ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData)
}
-Heap::DataView::DataView(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->dataViewPrototype()),
- buffer(0),
- byteLength(0),
- byteOffset(0)
-{
-}
-
-
void DataView::markObjects(Heap::Base *that, ExecutionEngine *e)
{
DataView::Data *v = static_cast<DataView::Data *>(that);
@@ -103,22 +94,30 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getUint8"), method_getChar<unsigned char>, 0);
defineDefaultProperty(QStringLiteral("getInt16"), method_get<short>, 0);
- defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getUint16"), method_get<unsigned short>, 0);
defineDefaultProperty(QStringLiteral("getInt32"), method_get<int>, 0);
- defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("getUint32"), method_get<unsigned int>, 0);
defineDefaultProperty(QStringLiteral("getFloat32"), method_getFloat<float>, 0);
defineDefaultProperty(QStringLiteral("getFloat64"), method_getFloat<double>, 0);
defineDefaultProperty(QStringLiteral("setInt8"), method_setChar<signed char>, 0);
- defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setUint8"), method_setChar<unsigned char>, 0);
defineDefaultProperty(QStringLiteral("setInt16"), method_set<short>, 0);
- defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setUint16"), method_set<unsigned short>, 0);
defineDefaultProperty(QStringLiteral("setInt32"), method_set<int>, 0);
- defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setUint32"), method_set<unsigned int>, 0);
defineDefaultProperty(QStringLiteral("setFloat32"), method_setFloat<float>, 0);
defineDefaultProperty(QStringLiteral("setFloat64"), method_setFloat<double>, 0);
+
+ // For backword compatibility
+ defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
}
ReturnedValue DataViewPrototype::method_get_buffer(CallContext *ctx)
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index e98239396a..37a8363645 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -47,7 +47,7 @@ struct DataViewCtor : FunctionObject {
};
struct DataView : Object {
- DataView(ExecutionEngine *e);
+ DataView() {}
Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
@@ -66,6 +66,7 @@ struct DataViewCtor: FunctionObject
struct DataView : Object
{
V4_OBJECT2(DataView, Object)
+ V4_PROTOTYPE(dataViewPrototype)
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 3f45751695..a6e1f47d91 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -628,8 +628,7 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
- : Heap::Object(engine->emptyClass, engine->datePrototype())
+Heap::DateObject::DateObject(const QDateTime &date)
{
this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN();
}
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 7a6413e820..a324e216e4 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -46,18 +46,16 @@ namespace QV4 {
namespace Heap {
struct DateObject : Object {
- DateObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
+ DateObject()
{
date = qSNaN();
}
- DateObject(QV4::ExecutionEngine *engine, const Value &date)
- : Object(engine->emptyClass, engine->datePrototype())
+ DateObject(const Value &date)
{
this->date = date.toNumber();
}
- DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
+ DateObject(const QDateTime &date);
double date;
};
@@ -71,6 +69,7 @@ struct DateCtor : FunctionObject {
struct DateObject: Object {
V4_OBJECT2(DateObject, Object)
Q_MANAGED_TYPE(DateObject)
+ V4_PROTOTYPE(datePrototype)
double date() const { return d()->date; }
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 6efc3793ce..79fd58f700 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -66,17 +66,16 @@ void Debugger::JavaScriptJob::run()
{
Scope scope(engine);
- ExecutionContextSaver saver(scope, engine->currentContext());
+ ExecutionContextSaver saver(scope);
+ ExecutionContext *ctx = engine->currentContext;
if (frameNr > 0) {
- Value *savedContexts = scope.alloc(frameNr);
for (int i = 0; i < frameNr; ++i) {
- savedContexts[i] = engine->currentContext();
- engine->popContext();
+ ctx = engine->parentContext(ctx);
}
+ engine->pushContext(ctx);
}
- ScopedContext ctx(scope, engine->currentContext());
QV4::Script script(ctx, this->script);
script.strictMode = ctx->d()->strictMode;
// In order for property lookups in QML to work, we need to disable fast v4 lookups. That
@@ -151,7 +150,7 @@ void Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue.set(m_engine, Encode::undefined());
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
m_stepping = speed;
m_runningCondition.wakeAll();
}
@@ -181,7 +180,7 @@ Debugger::ExecutionState Debugger::currentExecutionState() const
{
ExecutionState state;
state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->currentContext()->lineNumber;
+ state.lineNumber = engine()->current->lineNumber;
return state;
}
@@ -206,7 +205,7 @@ void Debugger::maybeBreakAtInstruction()
switch (m_stepping) {
case StepOver:
- if (m_currentContext.asManaged()->d() != m_engine->currentContext())
+ if (m_currentContext.asManaged()->d() != m_engine->current)
break;
// fall through
case StepIn:
@@ -222,7 +221,7 @@ void Debugger::maybeBreakAtInstruction()
pauseAndWait(PauseRequest);
} else if (m_haveBreakPoints) {
if (Function *f = getFunction()) {
- const int lineNumber = engine()->currentContext()->lineNumber;
+ const int lineNumber = engine()->current->lineNumber;
if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
pauseAndWait(BreakPoint);
}
@@ -236,7 +235,7 @@ void Debugger::enteringFunction()
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
}
}
@@ -248,8 +247,8 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->currentContext()) {
- m_currentContext.set(m_engine, m_engine->currentContext()->parent);
+ if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
+ m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
@@ -270,7 +269,7 @@ void Debugger::aboutToThrow()
Function *Debugger::getFunction() const
{
Scope scope(m_engine);
- ScopedContext context(scope, m_engine->currentContext());
+ ExecutionContext *context = m_engine->currentContext;
ScopedFunctionObject function(scope, context->getFunctionObject());
if (function)
return function->function();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index caf07e8b0b..6fe14da850 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -200,6 +200,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
+ , currentContext(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, debugger(0)
@@ -297,10 +298,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
- jsObjects[ObjectProto] = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
+ jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(emptyClass);
arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
- jsObjects[ArrayProto] = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype());
+ jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(arrayClass, objectPrototype());
InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable);
argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
@@ -311,15 +312,17 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
Q_ASSERT(globalObject->d()->vtable());
initRootContext();
- jsObjects[StringProto] = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype());
- jsObjects[NumberProto] = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype());
- jsObjects[BooleanProto] = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype());
- jsObjects[DateProto] = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype());
+ stringClass = emptyClass->addMember(id_length(), Attr_ReadOnly);
+ Q_ASSERT(stringClass->find(id_length()) == Heap::StringObject::LengthPropertyIndex);
+ jsObjects[StringProto] = memoryManager->allocObject<StringPrototype>(stringClass, objectPrototype());
+ jsObjects[NumberProto] = memoryManager->allocObject<NumberPrototype>(emptyClass, objectPrototype());
+ jsObjects[BooleanProto] = memoryManager->allocObject<BooleanPrototype>(emptyClass, objectPrototype());
+ jsObjects[DateProto] = memoryManager->allocObject<DatePrototype>(emptyClass, objectPrototype());
uint index;
InternalClass *functionProtoClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- jsObjects[FunctionProto] = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype());
+ jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(functionProtoClass, objectPrototype());
functionClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index);
@@ -329,42 +332,72 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- jsObjects[RegExpProto] = memoryManager->alloc<RegExpPrototype>(this);
+ Scope scope(this);
+ ScopedString str(scope);
+ regExpObjectClass = emptyClass->addMember(id_lastIndex(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ Q_ASSERT(index == RegExpObject::Index_LastIndex);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("source"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Source);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("global"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Global);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("ignoreCase"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_IgnoreCase);
+ regExpObjectClass = regExpObjectClass->addMember((str = newIdentifier(QStringLiteral("multiline"))), Attr_ReadOnly, &index);
+ Q_ASSERT(index == RegExpObject::Index_Multiline);
+
+ jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(regExpObjectClass, objectPrototype());
regExpExecArrayClass = arrayClass->addMember(id_index(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
regExpExecArrayClass = regExpExecArrayClass->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- jsObjects[ErrorProto] = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype());
- jsObjects[EvalErrorProto] = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[RangeErrorProto] = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[ReferenceErrorProto] = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[SyntaxErrorProto] = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[TypeErrorProto] = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype());
- jsObjects[URIErrorProto] = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype());
-
- jsObjects[VariantProto] = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype());
+ errorClass = emptyClass->addMember((str = newIdentifier(QStringLiteral("stack"))), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_Stack);
+ errorClass = errorClass->addMember((str = newIdentifier(QStringLiteral("fileName"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_FileName);
+ errorClass = errorClass->addMember((str = newIdentifier(QStringLiteral("lineNumber"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_LineNumber);
+ errorClassWithMessage = errorClass->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorObject::Index_Message);
+ errorProtoClass = emptyClass->addMember(id_constructor(), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Constructor);
+ errorProtoClass = errorProtoClass->addMember((str = newIdentifier(QStringLiteral("message"))), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Message);
+ errorProtoClass = errorProtoClass->addMember(id_name(), Attr_Data|Attr_NotEnumerable, &index);
+ Q_ASSERT(index == ErrorPrototype::Index_Name);
+
+ jsObjects[GetStack_Function] = BuiltinFunction::create(rootContext(), str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack);
+ getStackFunction()->defineReadonlyProperty(id_length(), Primitive::fromInt32(0));
+
+ jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(errorProtoClass, objectPrototype());
+ jsObjects[EvalErrorProto] = memoryManager->allocObject<EvalErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[RangeErrorProto] = memoryManager->allocObject<RangeErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[ReferenceErrorProto] = memoryManager->allocObject<ReferenceErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[SyntaxErrorProto] = memoryManager->allocObject<SyntaxErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[TypeErrorProto] = memoryManager->allocObject<TypeErrorPrototype>(errorProtoClass, errorPrototype());
+ jsObjects[URIErrorProto] = memoryManager->allocObject<URIErrorPrototype>(errorProtoClass, errorPrototype());
+
+ jsObjects[VariantProto] = memoryManager->allocObject<VariantPrototype>(emptyClass, objectPrototype());
Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d());
- Scope scope(this);
- jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype()));
-
- ScopedContext global(scope, rootContext());
- jsObjects[Object_Ctor] = memoryManager->alloc<ObjectCtor>(global);
- jsObjects[String_Ctor] = memoryManager->alloc<StringCtor>(global);
- jsObjects[Number_Ctor] = memoryManager->alloc<NumberCtor>(global);
- jsObjects[Boolean_Ctor] = memoryManager->alloc<BooleanCtor>(global);
- jsObjects[Array_Ctor] = memoryManager->alloc<ArrayCtor>(global);
- jsObjects[Function_Ctor] = memoryManager->alloc<FunctionCtor>(global);
- jsObjects[Date_Ctor] = memoryManager->alloc<DateCtor>(global);
- jsObjects[RegExp_Ctor] = memoryManager->alloc<RegExpCtor>(global);
- jsObjects[Error_Ctor] = memoryManager->alloc<ErrorCtor>(global);
- jsObjects[EvalError_Ctor] = memoryManager->alloc<EvalErrorCtor>(global);
- jsObjects[RangeError_Ctor] = memoryManager->alloc<RangeErrorCtor>(global);
- jsObjects[ReferenceError_Ctor] = memoryManager->alloc<ReferenceErrorCtor>(global);
- jsObjects[SyntaxError_Ctor] = memoryManager->alloc<SyntaxErrorCtor>(global);
- jsObjects[TypeError_Ctor] = memoryManager->alloc<TypeErrorCtor>(global);
- jsObjects[URIError_Ctor] = memoryManager->alloc<URIErrorCtor>(global);
+ jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->allocObject<SequencePrototype>(arrayClass, arrayPrototype()));
+
+ ExecutionContext *global = rootContext();
+ jsObjects[Object_Ctor] = memoryManager->allocObject<ObjectCtor>(global);
+ jsObjects[String_Ctor] = memoryManager->allocObject<StringCtor>(global);
+ jsObjects[Number_Ctor] = memoryManager->allocObject<NumberCtor>(global);
+ jsObjects[Boolean_Ctor] = memoryManager->allocObject<BooleanCtor>(global);
+ jsObjects[Array_Ctor] = memoryManager->allocObject<ArrayCtor>(global);
+ jsObjects[Function_Ctor] = memoryManager->allocObject<FunctionCtor>(global);
+ jsObjects[Date_Ctor] = memoryManager->allocObject<DateCtor>(global);
+ jsObjects[RegExp_Ctor] = memoryManager->allocObject<RegExpCtor>(global);
+ jsObjects[Error_Ctor] = memoryManager->allocObject<ErrorCtor>(global);
+ jsObjects[EvalError_Ctor] = memoryManager->allocObject<EvalErrorCtor>(global);
+ jsObjects[RangeError_Ctor] = memoryManager->allocObject<RangeErrorCtor>(global);
+ jsObjects[ReferenceError_Ctor] = memoryManager->allocObject<ReferenceErrorCtor>(global);
+ jsObjects[SyntaxError_Ctor] = memoryManager->allocObject<SyntaxErrorCtor>(global);
+ jsObjects[TypeError_Ctor] = memoryManager->allocObject<TypeErrorCtor>(global);
+ jsObjects[URIError_Ctor] = memoryManager->allocObject<URIErrorCtor>(global);
static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor());
static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor());
@@ -388,18 +421,19 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
// typed arrays
- jsObjects[ArrayBuffer_Ctor] = memoryManager->alloc<ArrayBufferCtor>(global);
- jsObjects[ArrayBufferProto] = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype());
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->allocObject<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->allocObject<ArrayBufferPrototype>();
static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- jsObjects[DataView_Ctor] = memoryManager->alloc<DataViewCtor>(global);
- jsObjects[DataViewProto] = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype());
+ jsObjects[DataView_Ctor] = memoryManager->allocObject<DataViewCtor>(global);
+ jsObjects[DataViewProto] = memoryManager->allocObject<DataViewPrototype>();
static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor());
jsObjects[ValueTypeProto] = (Heap::Base *) 0;
+ jsObjects[SignalHandlerProto] = (Heap::Base *) 0;
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
- static_cast<Value &>(typedArrayCtors[i]) = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocObject<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
+ static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocObject<TypedArrayPrototype>(Heap::TypedArray::Type(i));
typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
}
@@ -428,19 +462,18 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
- ScopedString str(scope);
for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]);
ScopedObject o(scope);
- globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this)));
- globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocObject<MathObject>()));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocObject<JsonObject>()));
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
- jsObjects[Eval_Function] = memoryManager->alloc<EvalFunction>(global);
+ jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global);
globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
@@ -508,8 +541,11 @@ void ExecutionEngine::initRootContext()
r->d()->callData->argc = 0;
r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
+ jsObjects[RootContext] = r;
+ jsObjects[IntegerNull] = Encode((int)0);
- jsObjects[RootContect] = r;
+ currentContext = static_cast<ExecutionContext *>(jsObjects + RootContext);
+ current = currentContext->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -517,29 +553,31 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
return new (classPool) InternalClass(other);
}
-Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
+ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- Scope scope(this);
- Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
- g->d()->callData = rootContext()->d()->callData;
+ pushContext(rootContext()->d());
- Q_ASSERT(currentContext() == g->d());
- return g->d();
+ Q_ASSERT(current == rootContext()->d());
+ return currentContext;
+}
+
+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;
}
Heap::Object *ExecutionEngine::newObject()
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(this));
- return object->d();
+ return memoryManager->allocObject<Object>();
}
Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(internalClass, prototype));
- return object->d();
+ return memoryManager->allocObject<Object>(internalClass, prototype);
}
Heap::String *ExecutionEngine::newString(const QString &s)
@@ -555,29 +593,23 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text)
Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
- Scope scope(this);
- Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, string));
- return object->d();
+ return memoryManager->allocObject<StringObject>(string);
}
Heap::Object *ExecutionEngine::newNumberObject(double value)
{
- Scope scope(this);
- Scoped<NumberObject> object(scope, memoryManager->alloc<NumberObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<NumberObject>(value);
}
Heap::Object *ExecutionEngine::newBooleanObject(bool b)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<BooleanObject>(this, b));
- return object->d();
+ return memoryManager->allocObject<BooleanObject>(b);
}
Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>());
if (count) {
if (count < 0x1000)
@@ -587,39 +619,60 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
return object->d();
}
+Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int length)
+{
+ Scope scope(this);
+ ScopedArrayObject a(scope, memoryManager->allocObject<ArrayObject>());
+
+ if (length) {
+ size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value);
+ Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size);
+ new (d) Heap::SimpleArrayData;
+ d->alloc = length;
+ d->type = Heap::ArrayData::Simple;
+ d->offset = 0;
+ d->len = length;
+ memcpy(&d->arrayData, values, length*sizeof(Value));
+ a->d()->arrayData = d;
+ a->setArrayLengthUnchecked(length);
+ }
+ return a->d();
+}
+
Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this, list));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(list));
return object->d();
}
-Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *prototype)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *internalClass, Object *prototype)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic, prototype));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(internalClass, prototype));
return object->d();
}
Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array)
{
- Scope scope(this);
- Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array));
- return object->d();
+ return memoryManager->allocObject<ArrayBuffer>(array);
+}
+
+Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(size_t length)
+{
+ return memoryManager->allocObject<ArrayBuffer>(length);
}
Heap::DateObject *ExecutionEngine::newDateObject(const Value &value)
{
- Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, value));
- return object->d();
+ return memoryManager->allocObject<DateObject>(value);
}
Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
{
Scope scope(this);
- Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, dt));
+ Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(dt));
return object->d();
}
@@ -640,97 +693,75 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int
Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
{
- Scope scope(this);
- Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re, global));
- return object->d();
+ return memoryManager->allocObject<RegExpObject>(re, global);
}
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
- Scope scope(this);
- Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re));
- return object->d();
+ return memoryManager->allocObject<RegExpObject>(re);
}
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype(), value));
- return object->d();
+ return ErrorObject::create<ErrorObject>(this, value);
}
Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedString s(scope, newString(message));
- ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, s));
- return error->d();
+ return ErrorObject::create<SyntaxErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Scope scope(this);
- ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, message, fileName, line, column));
- return error->d();
+ return ErrorObject::create<SyntaxErrorObject>(this, message, fileName, line, column);
}
Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<ReferenceErrorObject>(this, message);
}
-Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
+Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message, fileName, lineNumber, columnNumber));
- return o->d();
+ return ErrorObject::create<ReferenceErrorObject>(this, message, fileName, line, column);
}
Heap::Object *ExecutionEngine::newTypeErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<TypeErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<TypeErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newRangeErrorObject(const QString &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<RangeErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<RangeErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newURIErrorObject(const Value &message)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<URIErrorObject>(this, message));
- return o->d();
+ return ErrorObject::create<URIErrorObject>(this, message);
}
Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
{
- Scope scope(this);
- ScopedObject o(scope, memoryManager->alloc<VariantObject>(this, v));
- return o->d();
+ return memoryManager->allocObject<VariantObject>(v);
}
Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
{
Scope scope(this);
- ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(this, o));
+ ScopedObject obj(scope, memoryManager->allocObject<ForEachIteratorObject>(o));
return obj->d();
}
Heap::QmlContext *ExecutionEngine::qmlContext() const
{
- Heap::ExecutionContext *ctx = currentContext();
+ Heap::ExecutionContext *ctx = current;
+ // get the correct context when we're within a builtin function
if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
- ctx = ctx->parent;
+ ctx = parentContext(currentContext)->d();
if (!ctx->outer)
return 0;
@@ -745,18 +776,13 @@ Heap::QmlContext *ExecutionEngine::qmlContext() const
return static_cast<Heap::QmlContext *>(ctx);
}
-Heap::QmlContextWrapper *ExecutionEngine::qmlContextObject() const
+QObject *ExecutionEngine::qmlScopeObject() const
{
Heap::QmlContext *ctx = qmlContext();
if (!ctx)
return 0;
- Q_ASSERT(ctx->qml);
- return ctx->qml;
-}
-QObject *ExecutionEngine::qmlScopeObject() const
-{
- return qmlContextObject()->scopeObject;
+ return ctx->qml->scopeObject;
}
ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
@@ -782,9 +808,11 @@ ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
QQmlContextData *ExecutionEngine::callingQmlContext() const
{
- Heap::QmlContextWrapper *w = qmlContextObject();
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
- return w ? w->context.contextData() : 0;
+ return ctx->qml->context.contextData();
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -793,7 +821,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
ScopedString name(scope);
QVector<StackFrame> stack;
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentContext;
ScopedFunctionObject function(scope);
while (c && frameLimit) {
function = c->getFunctionObject();
@@ -813,7 +841,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
stack.append(frame);
--frameLimit;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (frameLimit && globalCode) {
@@ -881,8 +909,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
return src;
QUrl base;
- Scope scope(this);
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentContext;
while (c) {
CallContext *callCtx = c->asCallContext();
if (callCtx && callCtx->d()->function) {
@@ -890,7 +917,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
base.setUrl(callCtx->d()->function->function->sourceFile());
break;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (base.isEmpty() && globalCode)
@@ -920,10 +947,10 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
memcpy(argumentsAccessors, oldAccessors, oldSize*sizeof(Property));
delete [] oldAccessors;
}
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = rootContext();
for (int i = oldSize; i < nArgumentsAccessors; ++i) {
- argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(global, i));
- argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(global, i));
+ argumentsAccessors[i].value = ScopedValue(scope, memoryManager->allocObject<ArgumentsGetterFunction>(global, i));
+ argumentsAccessors[i].set = ScopedValue(scope, memoryManager->allocObject<ArgumentsSetterFunction>(global, i));
}
}
}
@@ -940,16 +967,6 @@ void ExecutionEngine::markObjects()
setter->mark(this);
}
- Heap::ExecutionContext *c = currentContext();
- while (c) {
- Q_ASSERT(c->inUse());
- if (!c->isMarked()) {
- c->setMarkBit();
- c->vtable()->markObjects(c, this);
- }
- c = c->parent;
- }
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 90564a9652..ffcd904013 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -78,7 +78,6 @@ private:
friend struct Heap::ExecutionContext;
public:
Heap::ExecutionContext *current;
- Heap::ExecutionContext *currentContext() const { return current; }
Value *jsStackTop;
quint32 hasException;
@@ -88,6 +87,7 @@ public:
ExecutableAllocator *regExpAllocator;
QScopedPointer<EvalISelFactory> iselFactory;
+ ExecutionContext *currentContext;
Value *jsStackLimit;
quintptr cStackLimit;
@@ -127,7 +127,8 @@ public:
QV8Engine *v8Engine;
enum JSObjects {
- RootContect,
+ RootContext,
+ IntegerNull, // Has to come after the RootContext to make the context stack safe
ObjectProto,
ArrayProto,
StringProto,
@@ -148,6 +149,7 @@ public:
ArrayBufferProto,
DataViewProto,
ValueTypeProto,
+ SignalHandlerProto,
Object_Ctor,
String_Ctor,
@@ -168,13 +170,14 @@ public:
DataView_Ctor,
Eval_Function,
+ GetStack_Function,
ThrowerObject,
NJSObjects
};
Value *jsObjects;
enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
- GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContect); }
+ GlobalContext *rootContext() const { return reinterpret_cast<GlobalContext *>(jsObjects + RootContext); }
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); }
@@ -217,22 +220,30 @@ public:
Object *typedArrayPrototype;
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
+ Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
InternalClassPool *classPool;
InternalClass *emptyClass;
InternalClass *arrayClass;
+ InternalClass *stringClass;
InternalClass *functionClass;
InternalClass *simpleScriptFunctionClass;
InternalClass *protoClass;
InternalClass *regExpExecArrayClass;
+ InternalClass *regExpObjectClass;
InternalClass *argumentsObjectClass;
InternalClass *strictArgumentsObjectClass;
+ InternalClass *errorClass;
+ InternalClass *errorClassWithMessage;
+ InternalClass *errorProtoClass;
+
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); }
Property *argumentsAccessors;
@@ -347,9 +358,11 @@ public:
void enableDebugger();
void enableProfiler();
- Heap::ExecutionContext *pushGlobalContext();
- void pushContext(CallContext *context);
- Heap::ExecutionContext *popContext();
+ ExecutionContext *pushGlobalContext();
+ void pushContext(Heap::ExecutionContext *context);
+ void pushContext(ExecutionContext *context);
+ void popContext();
+ ExecutionContext *parentContext(ExecutionContext *context) const;
Heap::Object *newObject();
Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
@@ -362,10 +375,12 @@ public:
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(InternalClass *ic, Object *prototype);
Heap::ArrayBuffer *newArrayBuffer(const QByteArray &array);
+ Heap::ArrayBuffer *newArrayBuffer(size_t length);
Heap::DateObject *newDateObject(const Value &value);
Heap::DateObject *newDateObject(const QDateTime &dt);
@@ -378,7 +393,7 @@ public:
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 lineNumber, int columnNumber);
+ 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 Value &message);
@@ -388,7 +403,6 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
Heap::QmlContext *qmlContext() const;
- QV4::Heap::QmlContextWrapper *qmlContextObject() const;
QObject *qmlScopeObject() const;
ReturnedValue qmlSingletonWrapper(String *name);
QQmlContextData *callingQmlContext() const;
@@ -442,36 +456,33 @@ public:
void assertObjectBelongsToEngine(const Heap::Base &baseObject);
};
-inline void ExecutionEngine::pushContext(CallContext *context)
+inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
{
- Q_ASSERT(current && context && context->d());
- context->d()->parent = current;
- current = context->d();
+ Q_ASSERT(currentContext && context);
+ Value *v = jsAlloca(2);
+ v[0] = Encode(context);
+ v[1] = Encode((int)(v - static_cast<Value *>(currentContext)));
+ currentContext = static_cast<ExecutionContext *>(v);
+ current = currentContext->d();
}
-inline Heap::ExecutionContext *ExecutionEngine::popContext()
+inline void ExecutionEngine::pushContext(ExecutionContext *context)
{
- Q_ASSERT(current->parent);
- current = current->parent;
- Q_ASSERT(current);
- return current;
+ pushContext(context->d());
}
-inline
-Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
- : engine(engine)
- , parent(engine->currentContext())
- , outer(0)
- , lookups(0)
- , compilationUnit(0)
- , type(t)
- , strictMode(false)
- , lineNumber(-1)
+
+inline void ExecutionEngine::popContext()
{
- engine->current = this;
+ Q_ASSERT(jsStackTop > currentContext);
+ QV4::Value *offset = (currentContext + 1);
+ Q_ASSERT(offset->isInteger());
+ int o = offset->integerValue();
+ Q_ASSERT(o);
+ currentContext -= o;
+ current = currentContext->d();
}
-
inline
void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
@@ -487,11 +498,12 @@ void Heap::Base::mark(QV4::ExecutionEngine *engine)
inline void Value::mark(ExecutionEngine *e)
{
- if (!_val)
+ if (!isManaged())
return;
- Managed *m = as<Managed>();
- if (m)
- m->d()->mark(e);
+
+ Heap::Base *o = heapObject();
+ if (o)
+ o->mark(e);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index a6c2a25b91..87b7a88a2b 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -61,72 +61,49 @@
using namespace QV4;
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
- , stack(Q_NULLPTR)
+Heap::ErrorObject::ErrorObject()
{
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope, scope.engine->newString(QStringLiteral("Error")));
- e->defineDefaultProperty(QStringLiteral("name"), s);
-}
-
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const Value &message, ErrorType t)
- : Heap::Object(ic, prototype)
-{
- errorType = t;
+ if (internalClass == scope.engine->errorProtoClass)
+ return;
- Scope scope(ic->engine);
- Scoped<QV4::ErrorObject> e(scope, this);
-
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
-
- if (!message.isUndefined())
- e->defineDefaultProperty(QStringLiteral("message"), message);
- ScopedString s(scope);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
-
- e->d()->stackTrace = scope.engine->stackTrace();
- if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
- }
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ *propertyData(QV4::ErrorObject::Index_FileName) = Encode::undefined();
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined();
}
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorObject::ErrorType t)
- : Heap::Object(ic, prototype)
+Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t)
{
errorType = t;
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope);
-
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
- ScopedValue v(scope, scope.engine->newString(message));
- e->defineDefaultProperty(QStringLiteral("message"), v);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
e->d()->stackTrace = scope.engine->stackTrace();
if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
}
+
+ if (!message.isUndefined())
+ *propertyData(QV4::ErrorObject::Index_Message) = message;
}
-Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
- : Heap::Object(ic, prototype)
+Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
{
errorType = t;
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- ScopedString s(scope);
- e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
- e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
+ *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
+ *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
e->d()->stackTrace = scope.engine->stackTrace();
StackFrame frame;
@@ -136,12 +113,33 @@ Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const
e->d()->stackTrace.prepend(frame);
if (!e->d()->stackTrace.isEmpty()) {
- e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
- e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
+ *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source);
+ *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line);
}
- ScopedValue v(scope, scope.engine->newString(message));
- e->defineDefaultProperty(QStringLiteral("message"), v);
+ if (!message.isUndefined())
+ *propertyData(QV4::ErrorObject::Index_Message) = message;
+}
+
+const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
+{
+ switch (t) {
+ case Heap::ErrorObject::Error:
+ return "Error";
+ case Heap::ErrorObject::EvalError:
+ return "EvalError";
+ case Heap::ErrorObject::RangeError:
+ return "RangeError";
+ case Heap::ErrorObject::ReferenceError:
+ return "ReferenceError";
+ case Heap::ErrorObject::SyntaxError:
+ return "SyntaxError";
+ case Heap::ErrorObject::TypeError:
+ return "TypeError";
+ case Heap::ErrorObject::URIError:
+ return "URIError";
+ }
+ Q_UNREACHABLE();
}
ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
@@ -181,58 +179,43 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, SyntaxError)
-{
-}
-
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, fileName, lineNumber, columnNumber, SyntaxError)
-{
-}
-
-Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype(), message, EvalError)
-{
-}
-
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg)
+ : Heap::ErrorObject(msg, SyntaxError)
{
}
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, SyntaxError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
+Heap::EvalErrorObject::EvalErrorObject(const Value &message)
+ : Heap::ErrorObject(message, EvalError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError)
+Heap::RangeErrorObject::RangeErrorObject(const Value &message)
+ : Heap::ErrorObject(message, RangeError)
{
}
-Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), msg, fileName, lineNumber, columnNumber, ReferenceError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &message)
+ : Heap::ErrorObject(message, ReferenceError)
{
}
-Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
-Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
- : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError)
+Heap::TypeErrorObject::TypeErrorObject(const Value &message)
+ : Heap::ErrorObject(message, TypeError)
{
}
-Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype(), message, URIError)
+Heap::URIErrorObject::URIErrorObject(const Value &message)
+ : Heap::ErrorObject(message, URIError)
{
}
@@ -258,7 +241,7 @@ ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const ErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return Encode(scope.engine->newErrorObject(v));
+ return ErrorObject::create<ErrorObject>(scope.engine, v)->asReturnedValue();
}
ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData)
@@ -275,7 +258,7 @@ ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const EvalErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<EvalErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<EvalErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
@@ -287,7 +270,7 @@ ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const RangeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<RangeErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
@@ -299,7 +282,7 @@ ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData
{
Scope scope(static_cast<const ReferenceErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<ReferenceErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
@@ -311,7 +294,7 @@ ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const SyntaxErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<SyntaxErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
@@ -323,7 +306,7 @@ ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const TypeErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<TypeErrorObject>(scope.engine, v)->asReturnedValue();
}
Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
@@ -335,19 +318,21 @@ ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const URIErrorCtor *>(m)->engine());
ScopedValue v(scope, callData->argument(0));
- return (scope.engine->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue();
+ return ErrorObject::create<URIErrorObject>(scope.engine, v)->asReturnedValue();
}
-void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
+void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t)
{
Scope scope(engine);
ScopedString s(scope);
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
- obj->defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
- obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString()));
+ *obj->propertyData(Index_Constructor) = ctor;
+ *obj->propertyData(Index_Message) = engine->id_empty();
+ *obj->propertyData(Index_Name) = engine->newString(QString::fromLatin1(ErrorObject::className(t)));
+ if (t == Heap::ErrorObject::Error)
+ obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
}
ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index e0fbcb4d8d..7f3babaa79 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -35,6 +35,7 @@
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -55,10 +56,9 @@ struct ErrorObject : Object {
URIError
};
- ErrorObject(InternalClass *ic, QV4::Object *prototype);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const Value &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ ErrorObject();
+ ErrorObject(const Value &message, ErrorType t = Error);
+ ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error);
ErrorType errorType;
StackTrace stackTrace;
@@ -66,32 +66,29 @@ struct ErrorObject : Object {
};
struct EvalErrorObject : ErrorObject {
- EvalErrorObject(ExecutionEngine *engine, const Value &message);
+ EvalErrorObject(const Value &message);
};
struct RangeErrorObject : ErrorObject {
- RangeErrorObject(ExecutionEngine *engine, const Value &message);
- RangeErrorObject(ExecutionEngine *engine, const QString &msg);
+ RangeErrorObject(const Value &message);
};
struct ReferenceErrorObject : ErrorObject {
- ReferenceErrorObject(ExecutionEngine *engine, const Value &message);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ ReferenceErrorObject(const Value &message);
+ ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct SyntaxErrorObject : ErrorObject {
- SyntaxErrorObject(ExecutionEngine *engine, const Value &message);
- SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ SyntaxErrorObject(const Value &message);
+ SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
};
struct TypeErrorObject : ErrorObject {
- TypeErrorObject(ExecutionEngine *engine, const Value &message);
- TypeErrorObject(ExecutionEngine *engine, const QString &msg);
+ TypeErrorObject(const Value &message);
};
struct URIErrorObject : ErrorObject {
- URIErrorObject(ExecutionEngine *engine, const Value &message);
+ URIErrorObject(const Value &message);
};
struct ErrorCtor : Heap::FunctionObject {
@@ -130,12 +127,30 @@ struct ErrorObject: Object {
IsErrorObject = true
};
+ enum {
+ Index_Stack = 0, // Accessor Property
+ Index_FileName = 2,
+ Index_LineNumber = 3,
+ Index_Message = 4
+ };
+
V4_OBJECT2(ErrorObject, Object)
Q_MANAGED_TYPE(ErrorObject)
+ V4_INTERNALCLASS(errorClass)
+ V4_PROTOTYPE(errorPrototype)
V4_NEEDS_DESTROY
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const Value &message);
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const QString &message);
+ template <typename T>
+ static Heap::Object *create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column);
+
SyntaxErrorObject *asSyntaxError();
+ static const char *className(Heap::ErrorObject::ErrorType t);
+
static ReturnedValue method_get_stack(CallContext *ctx);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -147,34 +162,40 @@ inline const ErrorObject *Value::as() const {
struct EvalErrorObject: ErrorObject {
typedef Heap::EvalErrorObject Data;
+ V4_PROTOTYPE(evalErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct RangeErrorObject: ErrorObject {
typedef Heap::RangeErrorObject Data;
+ V4_PROTOTYPE(rangeErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct ReferenceErrorObject: ErrorObject {
typedef Heap::ReferenceErrorObject Data;
+ V4_PROTOTYPE(referenceErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct SyntaxErrorObject: ErrorObject {
V4_OBJECT2(SyntaxErrorObject, ErrorObject)
+ V4_PROTOTYPE(syntaxErrorPrototype)
};
struct TypeErrorObject: ErrorObject {
typedef Heap::TypeErrorObject Data;
+ V4_PROTOTYPE(typeErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct URIErrorObject: ErrorObject {
typedef Heap::URIErrorObject Data;
+ V4_PROTOTYPE(uRIErrorPrototype)
const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
@@ -232,40 +253,45 @@ struct URIErrorCtor: ErrorCtor
struct ErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this); }
+ enum {
+ Index_Constructor = 0,
+ Index_Message = 1,
+ Index_Name = 2
+ };
+ void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); }
- static void init(ExecutionEngine *engine, Object *ctor, Object *obj);
+ static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t);
static ReturnedValue method_toString(CallContext *ctx);
};
struct EvalErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::EvalError); }
};
struct RangeErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::RangeError); }
};
struct ReferenceErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::ReferenceError); }
};
struct SyntaxErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::SyntaxError); }
};
struct TypeErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::TypeError); }
};
struct URIErrorPrototype : ErrorObject
{
- void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::URIError); }
};
@@ -274,6 +300,25 @@ inline SyntaxErrorObject *ErrorObject::asSyntaxError()
return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
}
+
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const Value &message) {
+ return e->memoryManager->allocObject<T>(message.isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), message);
+}
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message) {
+ Scope scope(e);
+ ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
+ return e->memoryManager->allocObject<T>(v->isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), v);
+}
+template <typename T>
+Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column) {
+ Scope scope(e);
+ ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
+ return e->memoryManager->allocObject<T>(v->isUndefined() ? e->errorClass : e->errorClassWithMessage, T::defaultPrototype(e), v, filename, line, column);
+}
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 98a4490211..66b2125a4f 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -70,14 +70,45 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)));
}
}
+ nFormals = compiledFunction->nFormals;
const quint32 *localsIndices = compiledFunction->localsTable();
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+
+ activationRequired = compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject));
}
Function::~Function()
{
}
+void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters)
+{
+ internalClass = engine->emptyClass;
+
+ // iterate backwards, so we get the right ordering for duplicate names
+ Scope scope(engine);
+ ScopedString arg(scope);
+ for (int i = parameters.size() - 1; i >= 0; --i) {
+ arg = engine->newString(QString::fromUtf8(parameters.at(i)));
+ while (1) {
+ InternalClass *newClass = internalClass->addMember(arg, Attr_NotConfigurable);
+ if (newClass != internalClass) {
+ internalClass = newClass;
+ break;
+ }
+ // duplicate arguments, need some trick to store them
+ arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)));
+ }
+ }
+ nFormals = parameters.size();
+
+ const quint32 *localsIndices = compiledFunction->localsTable();
+ for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
+ internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
+
+ activationRequired = true;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 10a03bca94..534aa1b750 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -49,11 +49,16 @@ struct Q_QML_EXPORT Function {
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
+ uint nFormals;
+ bool activationRequired;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
ReturnedValue (*codePtr)(ExecutionEngine *, const uchar *));
~Function();
+ // used when dynamically assigning signal handlers (QQmlConnection)
+ void updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters);
+
inline Heap::String *name() {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
@@ -64,7 +69,7 @@ struct Q_QML_EXPORT Function {
inline bool isNamedExpression() const { return compiledFunction->flags & CompiledData::Function::IsNamedExpression; }
inline bool needsActivation() const
- { return compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject)); }
+ { return activationRequired; }
};
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 6412e65fa9..a94c3f6db5 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -63,8 +63,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -73,8 +72,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -84,8 +82,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope->engine());
@@ -95,8 +92,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
- , scope(scope)
+ : scope(scope)
, function(Q_NULLPTR)
{
Scope s(scope->engine);
@@ -106,8 +102,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam
}
Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype())
- , scope(scope->d())
+ : scope(scope->d())
, function(Q_NULLPTR)
{
Scope s(scope);
@@ -117,8 +112,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne
}
Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
- : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype())
- , scope(scope)
+ : scope(scope)
, function(Q_NULLPTR)
{
Scope s(scope->engine);
@@ -127,15 +121,12 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu
f->init(n, false);
}
-Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
- , scope(ic->engine->rootContext()->d())
+Heap::FunctionObject::FunctionObject()
+ : scope(internalClass->engine->rootContext()->d())
, function(Q_NULLPTR)
{
- Scope scope(ic->engine);
- ScopedObject o(scope, this);
- o->ensureMemberIndex(ic->engine, Index_Prototype);
- memberData->data[Index_Prototype] = Encode::undefined();
+ Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
+ *propertyData(Index_Prototype) = Encode::undefined();
}
@@ -150,14 +141,14 @@ void FunctionObject::init(String *n, bool createProto)
Scope s(internalClass()->engine);
ScopedValue protectThis(s, this);
- ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
+ Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()) == Heap::FunctionObject::Index_Prototype);
if (createProto) {
ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
- proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor);
- proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue();
- memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue();
+ Q_ASSERT(s.engine->protoClass->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor);
+ *proto->propertyData(Heap::FunctionObject::Index_ProtoConstructor) = this->asReturnedValue();
+ *propertyData(Heap::FunctionObject::Index_Prototype) = proto.asReturnedValue();
} else {
- memberData()->data[Heap::FunctionObject::Index_Prototype] = Encode::undefined();
+ *propertyData(Heap::FunctionObject::Index_Prototype) = Encode::undefined();
}
ScopedValue v(s, n);
@@ -202,10 +193,28 @@ Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *sco
function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount ||
function->isNamedExpression())
- return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function);
- return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
+ return scope->d()->engine->memoryManager->allocObject<ScriptFunction>(scope, function);
+ return scope->d()->engine->memoryManager->allocObject<SimpleScriptFunction>(scope, function, createProto);
}
+Heap::FunctionObject *FunctionObject::createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
+{
+ ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
+ QV4::Scope valueScope(engine);
+ ExecutionContext *global = valueScope.engine->rootContext();
+ QV4::Scoped<QmlContext> wrapperContext(valueScope, global->newQmlContext(qmlContext, scopeObject));
+
+ if (!signalParameters.isEmpty()) {
+ if (error)
+ QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
+ runtimeFunction->updateInternalClass(engine, signalParameters);
+ }
+
+ QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
+ return function->d();
+}
+
+
bool FunctionObject::isBinding() const
{
return d()->vtable() == QQmlBindingFunction::staticVTable();
@@ -240,7 +249,7 @@ ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
{
Scope scope(static_cast<const Object *>(that)->engine());
Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that));
- ScopedContext ctx(scope, scope.engine->currentContext());
+
QString arguments;
QString body;
if (callData->argc > 0) {
@@ -251,7 +260,7 @@ ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
}
body = callData->args[callData->argc - 1].toQString();
}
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
@@ -281,7 +290,7 @@ ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = isel->compile();
Function *vmf = compilationUnit->linkToEngine(scope.engine);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = scope.engine->rootContext();
return FunctionObject::createScriptFunction(global, vmf)->asReturnedValue();
}
@@ -293,8 +302,7 @@ ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(FunctionPrototype);
-Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype)
- : Heap::FunctionObject(ic, prototype)
+Heap::FunctionPrototype::FunctionPrototype()
{
}
@@ -392,12 +400,12 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
ScopedValue boundThis(scope, ctx->argument(0));
Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
if (ctx->argc() > 1) {
- boundArgs = MemberData::reallocate(scope.engine, 0, ctx->argc() - 1);
+ boundArgs = MemberData::allocate(scope.engine, ctx->argc() - 1);
boundArgs->d()->size = ctx->argc() - 1;
memcpy(boundArgs->data(), ctx->args() + 1, (ctx->argc() - 1)*sizeof(Value));
}
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = scope.engine->rootContext();
return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue();
}
@@ -416,17 +424,18 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
+
Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
ScopedObject obj(scope, v4->newObject(ic, proto));
- ScopedContext context(scope, v4->currentContext());
callData->thisObject = obj.asReturnedValue();
- Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
@@ -448,12 +457,12 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
- ScopedContext context(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
- Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
+ Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(f, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
@@ -465,7 +474,6 @@ ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
- : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype())
{
this->scope = scope->d();
@@ -482,9 +490,10 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
f->init(name, createProto);
f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount()));
} else {
- f->ensureMemberIndex(s.engine, Index_Length);
- memberData->data[Index_Name] = function->name();
- memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount());
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
+ Q_ASSERT(internalClass && internalClass->find(s.engine->id_name()) == Index_Name);
+ *propertyData(Index_Name) = function->name();
+ *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount());
}
if (scope->d()->strictMode) {
@@ -504,14 +513,14 @@ ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *cal
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
+
Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
InternalClass *ic = scope.engine->emptyClass;
ScopedObject proto(scope, f->protoForConstructor());
callData->thisObject = v4->newObject(ic, proto);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
-
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
ctx.mm_data = 0; // make sure we don't run into the assertion in setVTable when allocating a context on the stack
@@ -526,7 +535,8 @@ ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *cal
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
callData->args[i] = Encode::undefined();
- Q_ASSERT(v4->currentContext() == &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
@@ -546,9 +556,9 @@ ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
+ ExecutionContextSaver ctxSaver(scope);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
@@ -564,7 +574,8 @@ ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
callData->args[i] = Encode::undefined();
- Q_ASSERT(v4->currentContext() == &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
@@ -607,7 +618,7 @@ ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
@@ -616,10 +627,10 @@ ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<CallContext> sctx(scope, &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
- return f->d()->code(sctx);
+ return f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext));
}
ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
@@ -631,7 +642,7 @@ ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callDa
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
#ifndef QT_NO_DEBUG
@@ -640,10 +651,10 @@ ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callDa
ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<CallContext> sctx(scope, &ctx);
+ v4->pushContext(&ctx);
+ Q_ASSERT(v4->current == &ctx);
- return f->d()->code(sctx, f->d()->index);
+ return f->d()->code(static_cast<QV4::CallContext *>(v4->currentContext), f->d()->index);
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 2c6a195746..182f06f74e 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -58,10 +58,10 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name);
FunctionObject(ExecutionContext *scope, const ReturnedValue name);
- FunctionObject(InternalClass *ic, QV4::Object *prototype);
+ FunctionObject();
~FunctionObject();
- unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; }
+ unsigned int formalParameterCount() { return function ? function->nFormals : 0; }
unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
bool needsActivation() const { return function ? function->needsActivation() : false; }
@@ -74,7 +74,7 @@ struct FunctionCtor : FunctionObject {
};
struct FunctionPrototype : FunctionObject {
- FunctionPrototype(InternalClass *ic, QV4::Object *prototype);
+ FunctionPrototype();
};
struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
@@ -115,6 +115,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
V4_OBJECT2(FunctionObject, Object)
Q_MANAGED_TYPE(FunctionObject)
+ V4_INTERNALCLASS(functionClass)
+ V4_PROTOTYPE(functionPrototype)
V4_NEEDS_DESTROY
Heap::ExecutionContext *scope() const { return d()->scope; }
@@ -134,8 +136,10 @@ struct Q_QML_EXPORT FunctionObject: Object {
static ReturnedValue call(const Managed *that, CallData *d);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
+ static Heap::FunctionObject *createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
+ const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
- ReturnedValue protoProperty() { return memberData()->data[Heap::FunctionObject::Index_Prototype].asReturnedValue(); }
+ ReturnedValue protoProperty() { return propertyData(Heap::FunctionObject::Index_Prototype)->asReturnedValue(); }
bool needsActivation() const { return d()->needsActivation(); }
bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
@@ -178,7 +182,7 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
{
- return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
+ return scope->engine()->memoryManager->allocObject<BuiltinFunction>(scope, name, code);
}
static ReturnedValue construct(const Managed *, CallData *);
@@ -208,6 +212,7 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop
struct SimpleScriptFunction: FunctionObject {
V4_OBJECT2(SimpleScriptFunction, FunctionObject)
+ V4_INTERNALCLASS(simpleScriptFunctionClass)
static ReturnedValue construct(const Managed *, CallData *callData);
static ReturnedValue call(const Managed *that, CallData *callData);
@@ -228,7 +233,7 @@ struct BoundFunction: FunctionObject {
static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs)
{
- return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
+ return scope->engine()->memoryManager->allocObject<BoundFunction>(scope, target, boundThis, boundArgs);
}
Heap::FunctionObject *target() const { return d()->target; }
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index ec7b9b3f7d..110a2c9089 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -339,11 +339,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
ExecutionEngine *v4 = engine();
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
- ScopedContext parentContext(scope, v4->currentContext());
- ExecutionContextSaver ctxSaver(scope, parentContext);
-
- ScopedContext ctx(scope, parentContext.getPointer());
+ ExecutionContext *currentContext = v4->currentContext;
+ ExecutionContext *ctx = currentContext;
if (!directCall) {
// the context for eval should be the global scope, so we fake a root
@@ -358,10 +357,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
bool inheritContext = !ctx->d()->strictMode;
Script script(ctx, code, QStringLiteral("eval code"));
- script.strictMode = (directCall && parentContext->d()->strictMode);
+ script.strictMode = (directCall && currentContext->d()->strictMode);
script.inheritContext = inheritContext;
script.parse();
- if (scope.engine->hasException)
+ if (v4->hasException)
return Encode::undefined();
Function *function = script.function();
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 138d76bf4a..a5336ee44f 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -149,6 +149,22 @@ Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
return str->identifier;
}
+Heap::String *IdentifierTable::stringFromIdentifier(Identifier *i)
+{
+ if (!i)
+ return 0;
+
+ uint idx = i->hashValue % alloc;
+ while (1) {
+ Heap::String *e = entries[idx];
+ Q_ASSERT(e);
+ if (e->identifier == i)
+ return e;
+ ++idx;
+ idx %= alloc;
+ }
+}
+
Identifier *IdentifierTable::identifier(const QString &s)
{
return insertString(s)->identifier;
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index 58f808b4d5..d91ce623c1 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -74,6 +74,8 @@ public:
Identifier *identifierImpl(const Heap::String *str);
+ Heap::String *stringFromIdentifier(Identifier *i);
+
void mark(ExecutionEngine *e) {
for (int i = 0; i < alloc; ++i) {
Heap::String *entry = entries[i];
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 2eb61081c7..90c6738c46 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -49,11 +49,12 @@
QT_BEGIN_NAMESPACE
-QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
- const QV4::Value &qmlglobal, const QV4::Value &callback)
- : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
+QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
+ QV4::QmlContext *qmlContext, const QV4::Value &callback)
+ : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0)
{
- m_qmlglobal.set(engine, qmlglobal);
+ if (qmlContext)
+ m_qmlContext.set(engine, *qmlContext);
if (callback.as<QV4::FunctionObject>())
m_callbackFunction.set(engine, callback);
@@ -142,8 +143,8 @@ void QV4Include::finished()
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- QV4::ScopedObject qmlglobal(scope, m_qmlglobal.value());
- QV4::Script script(v4, qmlglobal, code, m_url.toString());
+ QV4::Scoped<QV4::QmlContext> qml(scope, m_qmlContext.value());
+ QV4::Script script(v4, qml, code, m_url.toString());
script.parse();
if (!scope.engine->hasException)
@@ -190,12 +191,10 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
QV4::ScopedValue result(scope);
- QV4::ScopedObject qmlcontextobject(scope, scope.engine->qmlContextObject());
+ QV4::Scoped<QV4::QmlContext> qmlcontext(scope, scope.engine->qmlContext());
if (localFile.isEmpty()) {
- QV4Include *i = new QV4Include(url, scope.engine, context,
- qmlcontextobject,
- callbackFunction);
+ QV4Include *i = new QV4Include(url, scope.engine, qmlcontext, callbackFunction);
result = i->result();
} else {
@@ -203,7 +202,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- script.reset(new QV4::Script(scope.engine, qmlcontextobject, jsUnit));
+ script.reset(new QV4::Script(scope.engine, qmlcontext, jsUnit));
} else {
QFile f(localFile);
@@ -212,7 +211,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- script.reset(new QV4::Script(scope.engine, qmlcontextobject, code, url.toString()));
+ script.reset(new QV4::Script(scope.engine, qmlcontext, code, url.toString()));
}
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 5ef4442b03..3e3cf5e770 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -76,8 +76,7 @@ private Q_SLOTS:
void finished();
private:
- QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
- const QV4::Value &qmlglobal, const QV4::Value &callback);
+ QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &callback);
~QV4Include();
QV4::ReturnedValue result();
@@ -95,8 +94,7 @@ private:
QV4::PersistentValue m_callbackFunction;
QV4::PersistentValue m_resultObject;
- QQmlGuardedContextData m_context;
- QV4::PersistentValue m_qmlglobal;
+ QV4::PersistentValue m_qmlContext;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a90e8e3689..8f0b1776d7 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -134,21 +134,64 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
Q_ASSERT(extensible);
}
+static void insertHoleIntoPropertyData(Object *object, int idx)
+{
+ int inlineSize = object->d()->inlineMemberSize;
+ int icSize = object->internalClass()->size;
+ int from = qMax(idx, inlineSize);
+ int to = from + 1;
+ if (from < icSize)
+ memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1);
+ if (from == idx)
+ return;
+ if (inlineSize < icSize)
+ *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1);
+ from = idx;
+ to = from + 1;
+ if (from < inlineSize - 1)
+ memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1);
+}
+
+static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
+{
+ int inlineSize = object->d()->inlineMemberSize;
+ int icSize = object->internalClass()->size;
+ int delta = (accessor ? 2 : 1);
+ int to = idx;
+ int from = to + delta;
+ if (from < inlineSize) {
+ memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value));
+ to = inlineSize - delta;
+ from = inlineSize;
+ }
+ if (to < inlineSize && from < icSize) {
+ Q_ASSERT(from >= inlineSize);
+ memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
+ to = inlineSize;
+ from = inlineSize + delta;
+ }
+ if (from < icSize + delta) {
+ Q_ASSERT(to >= inlineSize && from > to);
+ memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value));
+ }
+}
+
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
uint idx;
- InternalClass *newClass = object->internalClass()->changeMember(string->identifier(), data, &idx);
+ InternalClass *oldClass = object->internalClass();
+ InternalClass *newClass = oldClass->changeMember(string->identifier(), data, &idx);
if (index)
*index = idx;
- if (newClass->size > object->internalClass()->size) {
- Q_ASSERT(newClass->size == object->internalClass()->size + 1);
- memmove(object->memberData()->data + idx + 2, object->memberData()->data + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
- } else if (newClass->size < object->internalClass()->size) {
- Q_ASSERT(newClass->size == object->internalClass()->size - 1);
- memmove(object->memberData()->data + idx + 1, object->memberData()->data + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
- }
object->setInternalClass(newClass);
+ if (newClass->size > oldClass->size) {
+ Q_ASSERT(newClass->size == oldClass->size + 1);
+ insertHoleIntoPropertyData(object, idx + 1);
+ } else if (newClass->size < oldClass->size) {
+ Q_ASSERT(newClass->size == oldClass->size - 1);
+ removeFromPropertyData(object, idx + 1);
+ }
}
InternalClassTransition &InternalClass::lookupOrInsertTransition(const InternalClassTransition &t)
@@ -286,6 +329,8 @@ void InternalClass::removeMember(Object *object, Identifier *id)
Transition temp = { id, 0, -1 };
Transition &t = object->internalClass()->lookupOrInsertTransition(temp);
+ bool accessor = oldClass->propertyData.at(propIdx).isAccessor();
+
if (t.lookup) {
object->setInternalClass(t.lookup);
} else {
@@ -300,8 +345,10 @@ void InternalClass::removeMember(Object *object, Identifier *id)
object->setInternalClass(newClass);
}
- // remove the entry in memberdata
- memmove(object->memberData()->data + propIdx, object->memberData()->data + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
+ Q_ASSERT(object->internalClass()->size == oldClass->size - (accessor ? 2 : 1));
+
+ // remove the entry in the property data
+ removeFromPropertyData(object, propIdx, accessor);
t.lookup = object->internalClass();
Q_ASSERT(t.lookup);
@@ -352,20 +399,26 @@ InternalClass *InternalClass::frozen()
if (m_frozen)
return m_frozen;
- m_frozen = engine->emptyClass;
+ m_frozen = propertiesFrozen();
+ m_frozen = m_frozen->nonExtensible();
+
+ m_frozen->m_frozen = m_frozen;
+ m_frozen->m_sealed = m_frozen;
+ return m_frozen;
+}
+
+InternalClass *InternalClass::propertiesFrozen() const
+{
+ InternalClass *frozen = engine->emptyClass;
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
continue;
attrs.setWritable(false);
attrs.setConfigurable(false);
- m_frozen = m_frozen->addMember(nameMap.at(i), attrs);
+ frozen = frozen->addMember(nameMap.at(i), attrs);
}
- m_frozen = m_frozen->nonExtensible();
-
- m_frozen->m_frozen = m_frozen;
- m_frozen->m_sealed = m_frozen;
- return m_frozen;
+ return frozen;
}
void InternalClass::destroy()
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 80590fe72e..342870fcd6 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -233,6 +233,7 @@ struct InternalClass : public QQmlJS::Managed {
InternalClass *sealed();
InternalClass *frozen();
+ InternalClass *propertiesFrozen() const;
void destroy();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index f703e85399..f4f87f3aea 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -858,10 +858,9 @@ QString Stringify::JA(ArrayObject *a)
}
-Heap::JsonObject::JsonObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype())
+Heap::JsonObject::JsonObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2);
@@ -943,7 +942,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
{
if (value.isString())
- return engine->currentContext()->engine->newString(value.toString())->asReturnedValue();
+ return engine->newString(value.toString())->asReturnedValue();
else if (value.isDouble())
return Encode(value.toDouble());
else if (value.isBool())
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 1ad0e2c5de..61d44f206e 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -47,7 +47,7 @@ namespace QV4 {
namespace Heap {
struct JsonObject : Object {
- JsonObject(ExecutionEngine *e);
+ JsonObject();
};
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 443427b024..d97abdb461 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -43,7 +43,7 @@ using namespace QV4;
ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttributes *attrs)
{
ExecutionEngine *engine = o->engine();
- Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
+ Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
Heap::Object *obj = o->d();
while (i < Size && obj) {
@@ -53,7 +53,8 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
obj = obj->prototype;
@@ -65,7 +66,8 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
obj = obj->prototype;
@@ -77,7 +79,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
{
Heap::Object *obj = thisObject->d();
ExecutionEngine *engine = thisObject->engine();
- Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
+ Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
while (i < Size && obj) {
classList[i] = obj->internalClass;
@@ -86,7 +88,8 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
obj = obj->prototype;
@@ -98,7 +101,8 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ Value *v = obj->propertyData(index);
+ return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
obj = obj->prototype;
@@ -165,7 +169,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
{
uint idx = index.asArrayIndex();
if (idx == UINT_MAX || !object.isObject())
- return indexedGetterGeneric(l, object, index);
+ return indexedGetterFallback(l, object, index);
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
@@ -251,7 +255,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
Q_ASSERT(object.isString());
proto = engine->stringPrototype();
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
if (name->equals(engine->id_length())) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
@@ -329,7 +333,7 @@ ReturnedValue Lookup::getterFallback(Lookup *l, ExecutionEngine *engine, const V
QV4::ScopedObject o(scope, object.toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
return o->get(name);
}
@@ -340,7 +344,7 @@ ReturnedValue Lookup::getter0(Lookup *l, ExecutionEngine *engine, const Value &o
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -353,7 +357,7 @@ ReturnedValue Lookup::getter1(Lookup *l, ExecutionEngine *engine, const Value &o
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
}
return getterTwoClasses(l, engine, object);
}
@@ -369,7 +373,7 @@ ReturnedValue Lookup::getter2(Lookup *l, ExecutionEngine *engine, const Value &o
if (l->classList[1] == p->internalClass) {
p = p->prototype;
if (l->classList[2] == p->internalClass)
- return p->memberData->data[l->index].asReturnedValue();
+ return p->propertyData(l->index)->asReturnedValue();
}
}
}
@@ -384,9 +388,9 @@ ReturnedValue Lookup::getter0getter0(Lookup *l, ExecutionEngine *engine, const V
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass())
- return o->memberData()->data[l->index2].asReturnedValue();
+ return o->propertyData(l->index2)->asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -399,10 +403,10 @@ ReturnedValue Lookup::getter0getter1(Lookup *l, ExecutionEngine *engine, const V
// the internal class won't match
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass() &&
l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return o->prototype()->propertyData(l->index2)->asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
@@ -416,10 +420,10 @@ ReturnedValue Lookup::getter1getter1(Lookup *l, ExecutionEngine *engine, const V
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
if (l->classList[2] == o->internalClass() &&
l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return o->prototype()->propertyData(l->index2)->asReturnedValue();
return getterFallback(l, engine, object);
}
l->getter = getterFallback;
@@ -435,7 +439,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, ExecutionEngine *engine, const
Object *o = object.objectValue();
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -457,7 +461,7 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, ExecutionEngine *engine, const
if (l->classList[0] == o->internalClass &&
l->classList[1] == o->prototype->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->prototype->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -482,7 +486,7 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, ExecutionEngine *engine, const
o = o->prototype;
if (l->classList[2] == o->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -502,7 +506,7 @@ ReturnedValue Lookup::primitiveGetter0(Lookup *l, ExecutionEngine *engine, const
if (object.type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -514,7 +518,7 @@ ReturnedValue Lookup::primitiveGetter1(Lookup *l, ExecutionEngine *engine, const
Object *o = l->proto;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -526,7 +530,7 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engin
Object *o = l->proto;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -546,7 +550,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype()->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -571,7 +575,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
if (const ArrayObject *a = object.as<ArrayObject>())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -603,7 +607,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
}
}
Scope scope(engine);
- ScopedString n(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString n(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
return engine->throwReferenceError(n);
}
@@ -611,7 +615,7 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass())
- return o->memberData()->data[l->index].asReturnedValue();
+ return o->propertyData(l->index)->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -622,7 +626,7 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData->data[l->index].asReturnedValue();
+ return o->prototype()->propertyData(l->index)->asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);
@@ -636,7 +640,7 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
if (l->classList[1] == o->internalClass) {
o = o->prototype;
if (l->classList[2] == o->internalClass) {
- return o->prototype->memberData->data[l->index].asReturnedValue();
+ return o->prototype->propertyData(l->index)->asReturnedValue();
}
}
}
@@ -649,7 +653,7 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
Object *o = engine->globalObject;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -667,7 +671,7 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
if (l->classList[0] == o->internalClass() &&
l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->prototype()->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -688,7 +692,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
o = o->prototype;
if (l->classList[2] == o->internalClass) {
Scope scope(o->internalClass->engine);
- ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
+ ScopedFunctionObject getter(scope, o->propertyData(l->index + Object::GetterOffset));
if (!getter)
return Encode::undefined();
@@ -710,7 +714,7 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, co
o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return;
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
o->put(name, value);
return;
}
@@ -741,7 +745,7 @@ void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c
QV4::Scope scope(engine);
QV4::ScopedObject o(scope, object.toObject(scope.engine));
if (o) {
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
o->put(name, value);
}
}
@@ -750,7 +754,7 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Va
{
Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
@@ -762,10 +766,8 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, co
Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -780,10 +782,8 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, co
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -800,10 +800,8 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, co
if (p && p->internalClass == l->classList[1]) {
p = p->prototype;
if (p && p->internalClass == l->classList[2]) {
- if (!o->memberData() || l->index >= o->memberData()->size)
- o->ensureMemberIndex(l->index);
- o->memberData()->data[l->index] = value;
o->setInternalClass(l->classList[3]);
+ *o->propertyData(l->index) = value;
return;
}
}
@@ -818,11 +816,11 @@ void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c
Object *o = object.as<Object>();
if (o) {
if (o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
if (o->internalClass() == l->classList[1]) {
- o->memberData()->data[l->index2] = value;
+ *o->propertyData(l->index2) = value;
return;
}
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index bb7ee43b4e..e2de36d18e 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -88,29 +88,7 @@ QString Managed::className() const
s = "RegExp";
break;
case Type_ErrorObject:
- switch (static_cast<Heap::ErrorObject *>(d())->errorType) {
- case Heap::ErrorObject::Error:
- s = "Error";
- break;
- case Heap::ErrorObject::EvalError:
- s = "EvalError";
- break;
- case Heap::ErrorObject::RangeError:
- s = "RangeError";
- break;
- case Heap::ErrorObject::ReferenceError:
- s = "ReferenceError";
- break;
- case Heap::ErrorObject::SyntaxError:
- s = "SyntaxError";
- break;
- case Heap::ErrorObject::TypeError:
- s = "TypeError";
- break;
- case Heap::ErrorObject::URIError:
- s = "URIError";
- break;
- }
+ s = ErrorObject::className(static_cast<Heap::ErrorObject *>(d())->errorType);
break;
case Type_ArgumentsObject:
s = "Arguments";
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index c498160c36..f1face007c 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -47,10 +47,9 @@ DEFINE_OBJECT_VTABLE(MathObject);
static const double qt_PI = 2.0 * ::asin(1.0);
-Heap::MathObject::MathObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype())
+Heap::MathObject::MathObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject m(scope, this);
m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(M_E));
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 472b2020b1..ff4fb12ee6 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -42,7 +42,7 @@ namespace QV4 {
namespace Heap {
struct MathObject : Object {
- MathObject(ExecutionEngine *e);
+ MathObject();
};
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index b3c0863e3e..ee3539c176 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -44,6 +44,7 @@
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
#include "qv4string_p.h"
+#include "qv4identifiertable_p.h"
#include <stdint.h>
@@ -51,15 +52,25 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(Object);
-Heap::Object::Object(InternalClass *internalClass, QV4::Object *prototype)
- : internalClass(internalClass),
- prototype(prototype ? prototype->d() : 0)
+void Object::setInternalClass(InternalClass *ic)
{
- if (internalClass->size) {
- Scope scope(internalClass->engine);
- ScopedObject o(scope, this);
- o->ensureMemberIndex(internalClass->engine, internalClass->size);
- }
+ d()->internalClass = ic;
+ ensureMemberData();
+}
+
+void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const
+{
+ p->value = *propertyData(index);
+ *attrs = internalClass()->propertyData.at(index);
+ if (attrs->isAccessor())
+ p->set = *propertyData(index + SetterOffset);
+}
+
+void Object::setProperty(uint index, const Property *p)
+{
+ *propertyData(index) = p->value;
+ if (internalClass()->propertyData.at(index).isAccessor())
+ *propertyData(index + SetterOffset) = p->set;
}
bool Object::setPrototype(Object *proto)
@@ -81,28 +92,32 @@ void Object::put(ExecutionEngine *engine, const QString &name, const Value &valu
put(n, value);
}
-ReturnedValue Object::getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs)
+ReturnedValue Object::getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
- return p->value.asReturnedValue();
- if (!p->getter())
+ return v.asReturnedValue();
+ const QV4::FunctionObject *f = v.as<FunctionObject>();
+ if (!f)
return Encode::undefined();
- Scope scope(p->getter()->internalClass->engine);
- ScopedFunctionObject getter(scope, p->getter());
+ Scope scope(f->engine());
ScopedCallData callData(scope);
callData->thisObject = thisObject;
- return getter->call(callData);
+ return f->call(callData);
}
-void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value)
+void Object::putValue(uint memberIndex, const Value &value)
{
- if (internalClass()->engine->hasException)
+ QV4::InternalClass *ic = internalClass();
+ if (ic->engine->hasException)
return;
+ PropertyAttributes attrs = ic->propertyData[memberIndex];
+
if (attrs.isAccessor()) {
- if (Heap::FunctionObject *set = pd->setter()) {
- Scope scope(set->internalClass->engine);
+ FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
+ if (set) {
+ Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
@@ -116,11 +131,11 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
if (!attrs.isWritable())
goto reject;
- pd->value = value;
+ *propertyData(memberIndex) = value;
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -137,7 +152,7 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- ScopedContext global(scope, e->rootContext());
+ ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
@@ -147,7 +162,7 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
{
ExecutionEngine *e = engine();
Scope scope(e);
- ScopedContext global(scope, e->rootContext());
+ ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
@@ -166,7 +181,7 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = v4->rootContext();
p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0)));
p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0)));
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -189,6 +204,12 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
{
Heap::Object *o = static_cast<Heap::Object *>(that);
+ if (o->inlineMemberSize) {
+ Value *v = o->propertyData(0);
+ for (uint i = 0; i < o->inlineMemberSize; ++i)
+ v[i].mark(e);
+ }
+
if (o->memberData)
o->memberData->mark(e);
if (o->arrayData)
@@ -197,9 +218,11 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
o->prototype->mark(e);
}
-void Object::ensureMemberIndex(uint idx)
+void Object::ensureMemberData()
{
- d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx);
+ QV4::InternalClass *ic = internalClass();
+ if (ic->size > d()->inlineMemberSize)
+ d()->memberData = MemberData::reallocate(ic->engine, d()->memberData, ic->size - d()->inlineMemberSize);
}
void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes)
@@ -207,15 +230,11 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
uint idx;
InternalClass::addMember(this, s, attributes, &idx);
-
- ensureMemberIndex(internalClass()->size);
-
if (attributes.isAccessor()) {
- Property *pp = propertyAt(idx);
- pp->value = p->value;
- pp->set = p->set;
+ *propertyData(idx + GetterOffset) = p->value;
+ *propertyData(idx + SetterOffset) = p->set;
} else {
- d()->memberData->data[idx] = p->value;
+ *propertyData(idx) = p->value;
}
}
@@ -229,8 +248,11 @@ void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p
uint member = internalClass()->find(name);
if (member < UINT_MAX) {
*attrs = internalClass()->propertyData[member];
- if (p)
- p->copy(propertyAt(member), *attrs);
+ if (p) {
+ p->value = *propertyData(member);
+ if (attrs->isAccessor())
+ p->set = *propertyData(member + SetterOffset);
+ }
return;
}
@@ -261,47 +283,44 @@ void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
}
// Section 8.12.2
-Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
{
Q_ASSERT(name->asArrayIndex() == UINT_MAX);
- const Heap::Object *o = d();
+ Heap::Object *o = d();
while (o) {
uint idx = o->internalClass->find(name);
if (idx < UINT_MAX) {
- if (attrs)
- *attrs = o->internalClass->propertyData[idx];
- return const_cast<Property *>(o->propertyAt(idx));
+ *attrs = o->internalClass->propertyData[idx];
+ return o->propertyData(attrs->isAccessor() ? idx + SetterOffset : idx);
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
-Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
{
- const Heap::Object *o = d();
+ Heap::Object *o = d();
while (o) {
Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
if (p) {
*attrs = o->arrayData->attributes(index);
- return p;
+ return attrs->isAccessor() ? &p->set : &p->value;
}
if (o->vtable()->type == Type_StringObject) {
if (index < static_cast<const Heap::StringObject *>(o)->length()) {
// this is an evil hack, but it works, as the method is only ever called from putIndexed,
// where we don't use the returned pointer there for non writable attributes
*attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return reinterpret_cast<Property *>(0x1);
+ return reinterpret_cast<Value *>(0x1);
}
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
@@ -466,7 +485,7 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
{
Scope scope(static_cast<Object *>(m)->engine());
ScopedObject o(scope, static_cast<Object *>(m));
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
InternalClass *c = o->internalClass();
uint idx = c->find(name);
@@ -475,12 +494,12 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->classList[0] = o->internalClass();
l->index = idx;
l->setter = Lookup::setter0;
- o->memberData()->data[idx] = value;
+ *o->propertyData(idx) = value;
return;
}
if (idx != UINT_MAX) {
- o->putValue(o->propertyAt(idx), o->internalClass()->propertyData[idx], value);
+ o->putValue(idx, value);
return;
}
}
@@ -568,13 +587,15 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
continue;
}
- Property *p = o->propertyAt(it->memberIndex);
+ int idx = it->memberIndex;
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- name->setM(o->engine()->newString(n->string));
+ name->setM(o->engine()->identifierTable->stringFromIdentifier(n));
*attrs = a;
- pd->copy(p, a);
+ pd->value = *o->propertyData(idx);
+ if (a.isAccessor())
+ pd->set = *o->propertyData(idx + SetterOffset);
return;
}
}
@@ -598,7 +619,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
if (idx < UINT_MAX) {
if (hasProperty)
*hasProperty = true;
- return getValue(o->propertyAt(idx), o->internalClass()->propertyData.at(idx));
+ return getValue(*o->propertyData(idx), o->internalClass()->propertyData.at(idx));
}
o = o->prototype();
@@ -637,7 +658,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
if (pd) {
if (hasProperty)
*hasProperty = true;
- return getValue(pd, attrs);
+ return getValue(pd->value, attrs);
}
if (hasProperty)
@@ -659,17 +680,17 @@ void Object::internalPut(String *name, const Value &value)
name->makeIdentifier(engine());
uint member = internalClass()->find(name);
- Property *pd = 0;
+ Value *v = 0;
PropertyAttributes attrs;
if (member < UINT_MAX) {
- pd = propertyAt(member);
attrs = internalClass()->propertyData[member];
+ v = propertyData(attrs.isAccessor() ? member + SetterOffset : member);
}
// clause 1
- if (pd) {
+ if (v) {
if (attrs.isAccessor()) {
- if (pd->setter())
+ if (v->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
@@ -685,7 +706,7 @@ void Object::internalPut(String *name, const Value &value)
if (!ok)
goto reject;
} else {
- pd->value = value;
+ *v = value;
}
return;
} else if (!prototype()) {
@@ -694,9 +715,9 @@ void Object::internalPut(String *name, const Value &value)
} else {
// clause 4
Scope scope(engine());
- if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(name, &attrs))) {
+ if ((v = ScopedObject(scope, prototype())->getValueOrSetter(name, &attrs))) {
if (attrs.isAccessor()) {
- if (!pd->setter())
+ if (!v->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -709,11 +730,11 @@ void Object::internalPut(String *name, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- Q_ASSERT(pd->setter() != 0);
+ if (v && attrs.isAccessor()) {
+ Q_ASSERT(v->as<FunctionObject>());
Scope scope(engine());
- ScopedFunctionObject setter(scope, pd->setter());
+ ScopedFunctionObject setter(scope, *v);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
@@ -725,7 +746,7 @@ void Object::internalPut(String *name, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode) {
+ if (engine()->current->strictMode) {
QString message = QStringLiteral("Cannot assign to read-only property \"");
message += name->toQString();
message += QLatin1Char('\"');
@@ -740,26 +761,24 @@ void Object::internalPutIndexed(uint index, const Value &value)
PropertyAttributes attrs;
- Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
- if (pd)
- attrs = arrayData()->attributes(index);
+ Value *v = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : 0;
- if (!pd && isStringObject()) {
+ if (!v && isStringObject()) {
if (index < static_cast<StringObject *>(this)->length())
// not writable
goto reject;
}
// clause 1
- if (pd) {
+ if (v) {
if (attrs.isAccessor()) {
- if (pd->setter())
+ if (v->as<FunctionObject>())
goto cont;
goto reject;
} else if (!attrs.isWritable())
goto reject;
else
- pd->value = value;
+ *v = value;
return;
} else if (!prototype()) {
if (!isExtensible())
@@ -767,9 +786,9 @@ void Object::internalPutIndexed(uint index, const Value &value)
} else {
// clause 4
Scope scope(engine());
- if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(index, &attrs))) {
+ if ((v = ScopedObject(scope, prototype())->getValueOrSetter(index, &attrs))) {
if (attrs.isAccessor()) {
- if (!pd->setter())
+ if (!v->as<FunctionObject>())
goto reject;
} else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
@@ -782,11 +801,11 @@ void Object::internalPutIndexed(uint index, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- Q_ASSERT(pd->setter() != 0);
+ if (v && attrs.isAccessor()) {
+ Q_ASSERT(v->as<FunctionObject>());
Scope scope(engine());
- ScopedFunctionObject setter(scope, pd->setter());
+ ScopedFunctionObject setter(scope, *v);
ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = this;
@@ -798,7 +817,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -820,7 +839,7 @@ bool Object::internalDeleteProperty(String *name)
InternalClass::removeMember(this, name->identifier());
return true;
}
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
return false;
}
@@ -838,7 +857,7 @@ bool Object::internalDeleteIndexedProperty(uint index)
if (!ad || ad->vtable()->del(this, index))
return true;
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
return false;
}
@@ -853,17 +872,16 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
Scope scope(engine);
name->makeIdentifier(scope.engine);
- Property *current;
- PropertyAttributes *cattrs;
uint memberIndex;
if (isArrayObject() && name->equals(engine->id_length())) {
Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()));
- Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex);
- cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex;
- if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs))
+ ScopedProperty lp(scope);
+ PropertyAttributes cattrs;
+ getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs);
+ if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
return true;
- if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
+ if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
goto reject;
bool succeeded = true;
if (attrs.type() == PropertyAttributes::Data) {
@@ -876,8 +894,10 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
}
succeeded = setArrayLength(l);
}
- if (attrs.hasWritable() && !attrs.isWritable())
- cattrs->setWritable(false);
+ if (attrs.hasWritable() && !attrs.isWritable()) {
+ cattrs.setWritable(false);
+ InternalClass::changeMember(this, engine->id_length(), cattrs);
+ }
if (!succeeded)
goto reject;
return true;
@@ -885,10 +905,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
// Clause 1
memberIndex = internalClass()->find(name);
- current = (memberIndex < UINT_MAX) ? propertyAt(memberIndex) : 0;
- cattrs = internalClass()->propertyData.constData() + memberIndex;
- if (!current) {
+ if (memberIndex == UINT_MAX) {
// clause 3
if (!isExtensible())
goto reject;
@@ -902,7 +920,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
return __defineOwnProperty__(engine, memberIndex, name, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -918,7 +936,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Pr
return defineOwnProperty2(engine, index, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -954,7 +972,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
return __defineOwnProperty__(engine, index, 0, p, attrs);
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -965,13 +983,14 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (attrs.isEmpty())
return true;
- Property *current = 0;
+ Scope scope(engine);
+ ScopedProperty current(scope);
PropertyAttributes cattrs;
if (member) {
- current = propertyAt(index);
+ getProperty(index, current, &cattrs);
cattrs = internalClass()->propertyData[index];
} else if (arrayData()) {
- current = arrayData()->getProperty(index);
+ arrayData()->getProperty(index, current, &cattrs);
cattrs = arrayData()->attributes(index);
}
@@ -1005,7 +1024,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
initSparseArray();
Q_ASSERT(arrayData());
setArrayAttributes(index, cattrs);
- current = arrayData()->getProperty(index);
}
current->setGetter(0);
current->setSetter(0);
@@ -1016,7 +1034,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (!member) {
// need to convert the array and the slot
setArrayAttributes(index, cattrs);
- current = arrayData()->getProperty(index);
}
current->value = Primitive::undefinedValue();
}
@@ -1040,12 +1057,14 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
current->merge(cattrs, p, attrs);
if (member) {
InternalClass::changeMember(this, member, cattrs);
+ setProperty(index, current);
} else {
setArrayAttributes(index, cattrs);
+ arrayData()->setProperty(index, current);
}
return true;
reject:
- if (engine->currentContext()->strictMode)
+ if (engine->current->strictMode)
engine->throwTypeError();
return false;
}
@@ -1135,11 +1154,11 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
-Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype())
+Heap::ArrayObject::ArrayObject(const QStringList &list)
+ : Heap::Object()
{
init();
- Scope scope(engine);
+ Scope scope(internalClass->engine);
ScopedObject a(scope, this);
// Converts a QStringList to JS.
@@ -1150,19 +1169,19 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
a->arrayReserve(len);
ScopedValue v(scope);
for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = engine->newString(list.at(ii))));
+ a->arrayPut(ii, (v = scope.engine->newString(list.at(ii))));
a->setArrayLengthUnchecked(len);
}
ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
if (name->equals(scope.engine->id_length())) {
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
}
return Object::getLookup(m, l);
}
@@ -1170,9 +1189,9 @@ ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
uint ArrayObject::getLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- if (a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].isInteger())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].integerValue();
- return Primitive::toUInt32(a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].doubleValue());
+ if (a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->isInteger())
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->integerValue();
+ return Primitive::toUInt32(a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->doubleValue());
}
QStringList ArrayObject::toQStringList() const
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index f129312819..58dab9691f 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -42,17 +42,19 @@
QT_BEGIN_NAMESPACE
+
namespace QV4 {
namespace Heap {
struct Object : Base {
- inline Object(ExecutionEngine *engine);
- Object(InternalClass *internal, QV4::Object *prototype);
+ inline Object() {}
- const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData->data + index); }
- Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData->data + index); }
+ const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ uint inlineMemberOffset;
+ uint inlineMemberSize;
InternalClass *internalClass;
Pointer<Object> prototype;
Pointer<MemberData> memberData;
@@ -80,6 +82,13 @@ struct Object : Base {
V4_MANAGED_SIZE_TEST \
QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
+#define V4_INTERNALCLASS(c) \
+ static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \
+ { return e->c; }
+#define V4_PROTOTYPE(p) \
+ static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
+ { return e->p(); }
+
struct ObjectVTable
{
VTable vTable;
@@ -124,21 +133,26 @@ const QV4::ObjectVTable classname::static_vtbl = \
struct Q_QML_EXPORT Object: Managed {
V4_OBJECT2(Object, Object)
Q_MANAGED_TYPE(Object)
+ V4_INTERNALCLASS(emptyClass)
+ V4_PROTOTYPE(objectPrototype)
enum {
- IsObject = true
+ IsObject = true,
+ GetterOffset = 0,
+ SetterOffset = 1
};
InternalClass *internalClass() const { return d()->internalClass; }
- void setInternalClass(InternalClass *ic) { d()->internalClass = ic; }
+ void setInternalClass(InternalClass *ic);
+
+ const Value *propertyData(uint index) const { return d()->propertyData(index); }
+ Value *propertyData(uint index) { return d()->propertyData(index); }
- Heap::MemberData *memberData() { return d()->memberData; }
- const Heap::MemberData *memberData() const { return d()->memberData; }
Heap::ArrayData *arrayData() const { return d()->arrayData; }
void setArrayData(ArrayData *a) { d()->arrayData = a->d(); }
- const Property *propertyAt(uint index) const { return d()->propertyAt(index); }
- Property *propertyAt(uint index) { return d()->propertyAt(index); }
+ void getProperty(uint index, Property *p, PropertyAttributes *attrs) const;
+ void setProperty(uint index, const Property *p);
const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype; }
@@ -147,8 +161,8 @@ struct Q_QML_EXPORT Object: Managed {
void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const;
- Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const;
+ Value *getValueOrSetter(String *name, PropertyAttributes *attrs);
+ Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -167,14 +181,14 @@ struct Q_QML_EXPORT Object: Managed {
//
void put(ExecutionEngine *engine, const QString &name, const Value &value);
- static ReturnedValue getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs);
- ReturnedValue getValue(const Property *p, PropertyAttributes attrs) const {
+ static ReturnedValue getValue(const Value &thisObject, const Value &v, PropertyAttributes attrs);
+ ReturnedValue getValue(const Value &v, PropertyAttributes attrs) const {
Scope scope(this->engine());
ScopedValue t(scope, const_cast<Object *>(this));
- return getValue(t, p, attrs);
+ return getValue(t, v, attrs);
}
- void putValue(Property *pd, PropertyAttributes attrs, const Value &value);
+ void putValue(uint memberIndex, const Value &value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
void defineDefaultProperty(String *name, const Value &value) {
@@ -189,10 +203,6 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, const Value &value);
void defineReadonlyProperty(String *name, const Value &value);
- void ensureMemberIndex(QV4::ExecutionEngine *e, uint idx) {
- d()->memberData = MemberData::reallocate(e, d()->memberData, idx);
- }
-
void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
ScopedProperty p(scope);
@@ -269,7 +279,6 @@ public:
return false;
}
- void ensureMemberIndex(uint idx);
inline ReturnedValue get(String *name, bool *hasProperty = 0) const
{ return vtable()->get(this, name, hasProperty); }
@@ -316,6 +325,8 @@ protected:
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
+ void ensureMemberData();
+
private:
ReturnedValue internalGet(String *name, bool *hasProperty) const;
ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
@@ -330,39 +341,19 @@ private:
namespace Heap {
-inline Object::Object(ExecutionEngine *engine)
- : internalClass(engine->emptyClass),
- prototype(static_cast<Object *>(engine->objectPrototype()->m()))
-{
-}
-
struct BooleanObject : Object {
- BooleanObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- b(false)
- {
- }
-
- BooleanObject(ExecutionEngine *engine, bool b)
- : Object(engine->emptyClass, engine->booleanPrototype()),
- b(b)
- {
- }
+ BooleanObject() {}
+ BooleanObject(bool b)
+ : b(b)
+ {}
bool b;
};
struct NumberObject : Object {
- NumberObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- value(0)
- {
- }
-
- NumberObject(ExecutionEngine *engine, double val)
- : Object(engine->emptyClass, engine->numberPrototype()),
- value(val)
- {
- }
+ NumberObject() {}
+ NumberObject(double val)
+ : value(val)
+ {}
double value;
};
@@ -371,15 +362,11 @@ struct ArrayObject : Object {
LengthPropertyIndex = 0
};
- ArrayObject(ExecutionEngine *engine)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype())
- { init(); }
- ArrayObject(ExecutionEngine *engine, const QStringList &list);
- ArrayObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+ ArrayObject()
{ init(); }
+ ArrayObject(const QStringList &list);
void init()
- { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); }
+ { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); }
};
}
@@ -387,6 +374,7 @@ struct ArrayObject : Object {
struct BooleanObject: Object {
V4_OBJECT2(BooleanObject, Object)
Q_MANAGED_TYPE(BooleanObject)
+ V4_PROTOTYPE(booleanPrototype)
bool value() const { return d()->b; }
@@ -395,6 +383,7 @@ struct BooleanObject: Object {
struct NumberObject: Object {
V4_OBJECT2(NumberObject, Object)
Q_MANAGED_TYPE(NumberObject)
+ V4_PROTOTYPE(numberPrototype)
double value() const { return d()->value; }
};
@@ -402,6 +391,8 @@ struct NumberObject: Object {
struct ArrayObject: Object {
V4_OBJECT2(ArrayObject, Object)
Q_MANAGED_TYPE(ArrayObject)
+ V4_INTERNALCLASS(arrayClass)
+ V4_PROTOTYPE(arrayPrototype)
void init(ExecutionEngine *engine);
@@ -415,7 +406,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- memberData()->data[Heap::ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
+ *propertyData(Heap::ArrayObject::LengthPropertyIndex) = Primitive::fromUInt32(l);
}
inline void Object::push_back(const Value &v)
@@ -438,10 +429,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a
arrayData()->vtable()->reallocate(this, index + 1, false);
}
setArrayAttributes(index, attributes);
- Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
- pd->value = p->value;
- if (attributes.isAccessor())
- pd->set = p->set;
+ ArrayData::insert(this, index, &p->value, attributes.isAccessor());
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
@@ -453,8 +441,7 @@ inline void Object::arraySet(uint index, const Value &value)
if (index > 0x1000 && index > 2*d()->arrayData->alloc) {
initSparseArray();
}
- Property *pd = ArrayData::insert(this, index);
- pd->value = value;
+ ArrayData::insert(this, index, &value);
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 585f9f5c2e..7f97872092 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -144,7 +144,7 @@ ReturnedValue ObjectIterator::nextPropertyName(Value *value)
if (attrs.isEmpty())
return Encode::null();
- *value = object->objectValue()->getValue(p, attrs);
+ *value = object->objectValue()->getValue(p->value, attrs);
if (!!name)
return name->asReturnedValue();
@@ -166,7 +166,7 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
if (attrs.isEmpty())
return Encode::null();
- *value = object->objectValue()->getValue(p, attrs);
+ *value = object->objectValue()->getValue(p->value, attrs);
if (!!name)
return name->asReturnedValue();
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index bfe04b33aa..e34b641be9 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -67,7 +67,7 @@ struct Q_QML_EXPORT ObjectIterator
namespace Heap {
struct ForEachIteratorObject : Object {
- ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o);
+ ForEachIteratorObject(QV4::Object *o);
ObjectIterator it;
Value workArea[2];
};
@@ -85,9 +85,8 @@ protected:
};
inline
-Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o)
- : Heap::Object(engine)
- , it(engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
+Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::Object *o)
+ : it(internalClass->engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
{
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 1edf76e2de..df7441ef5d 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -108,7 +108,7 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = v4->rootContext();
ScopedProperty p(scope);
p->value = BuiltinFunction::create(global, v4->id___proto__(), method_get_proto);
p->set = BuiltinFunction::create(global, v4->id___proto__(), method_set_proto);
@@ -141,9 +141,9 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property desc;
- O->getOwnProperty(name, &attrs, &desc);
- return fromPropertyDescriptor(scope.engine, &desc, attrs);
+ ScopedProperty desc(scope);
+ O->getOwnProperty(name, &attrs, desc);
+ return fromPropertyDescriptor(scope.engine, desc, attrs);
}
ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
@@ -222,7 +222,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
if (attrs.isEmpty())
break;
PropertyAttributes nattrs;
- val = o->getValue(pd, attrs);
+ val = o->getValue(pd->value, attrs);
toPropertyDescriptor(scope.engine, val, n, &nattrs);
if (scope.engine->hasException)
return Encode::undefined();
@@ -630,7 +630,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs)
{
- if (!desc)
+ if (attrs.isEmpty())
return Encode::undefined();
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 82e232d28c..ee294b3678 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -228,9 +228,8 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
}
}
-Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
- : Heap::Object(engine)
- , object(object)
+Heap::QObjectWrapper::QObjectWrapper(QObject *object)
+ : object(object)
{
}
@@ -255,7 +254,7 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
return result;
}
-ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
+ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
bool *hasProperty, bool includeImports) const
{
if (QQmlData::wasDeleted(d()->object)) {
@@ -264,20 +263,18 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return QV4::Encode::undefined();
}
- QV4::Scope scope(engine());
- QV4::ScopedString name(scope, n);
+ ExecutionEngine *v4 = engine();
- if (name->equals(scope.engine->id_destroy()) || name->equals(scope.engine->id_toString())) {
- int index = name->equals(scope.engine->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
- ScopedContext global(scope, scope.engine->rootContext());
- QV4::ScopedValue method(scope, QV4::QObjectMethod::create(global, d()->object, index));
+ if (name->equals(v4->id_destroy()) || name->equals(v4->id_toString())) {
+ int index = name->equals(v4->id_destroy()) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
if (hasProperty)
*hasProperty = true;
- return method->asReturnedValue();
+ ExecutionContext *global = v4->rootContext();
+ return QV4::QObjectMethod::create(global, d()->object, index);
}
QQmlPropertyData local;
- QQmlPropertyData *result = findProperty(scope.engine, qmlContext, name, revisionMode, &local);
+ QQmlPropertyData *result = findProperty(v4, qmlContext, name, revisionMode, &local);
if (!result) {
if (includeImports && name->startsWithUpper()) {
@@ -292,10 +289,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(scope.engine, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object,
r.type, Heap::QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(scope.engine, d()->object,
+ return QmlTypeWrapper::create(v4, d()->object,
qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
@@ -318,13 +315,11 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- return getProperty(scope.engine, d()->object, result);
+ return getProperty(v4, d()->object, result);
}
ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QV4::Scope scope(engine);
-
QQmlData::flushPendingBinding(object, property->coreIndex);
if (property->isFunction() && !property->isVarProperty()) {
@@ -333,24 +328,19 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- ScopedContext global(scope, scope.engine->qmlContext());
+ Scope scope(engine);
+ ScopedContext global(scope, engine->qmlContext());
return QV4::QObjectMethod::create(global, object, property->coreIndex);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(engine, object, property->coreIndex));
-
- QV4::ScopedString connect(scope, engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, engine->functionPrototype()->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, engine->functionPrototype()->get(disconnect)));
-
- return handler.asReturnedValue();
+ QmlSignalHandler::initProto(engine);
+ return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex)->asReturnedValue();
} else {
- ScopedContext global(scope, scope.engine->rootContext());
+ ExecutionContext *global = engine->rootContext();
return QV4::QObjectMethod::create(global, object, property->coreIndex);
}
}
- QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
if (property->hasAccessors()) {
QQmlNotifier *n = 0;
@@ -359,6 +349,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
+ Scope scope(engine);
QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired) {
@@ -390,7 +381,6 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
{
- QV4::Scope scope(engine);
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
*hasProperty = false;
@@ -403,6 +393,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
return QV4::Encode::null();
}
+ QV4::Scope scope(engine);
QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(engine, object));
if (!wrapper) {
if (hasProperty)
@@ -419,11 +410,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
QQmlPropertyData local;
- QQmlPropertyData *result = 0;
- {
- result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
- }
-
+ QQmlPropertyData *result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
if (!result)
return false;
@@ -433,8 +420,6 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
}
- Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
setProperty(engine, object, result, value);
return true;
}
@@ -686,7 +671,7 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
{
if (engine->jsEngine())
QQmlData::ensurePropertyCache(engine->jsEngine(), object);
- return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
+ return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue();
}
QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
@@ -1037,19 +1022,18 @@ void QObjectWrapper::destroyObject(bool lastCall)
if (!h->internalClass)
return; // destroyObject already got called
- QPointer<QObject> object = h->object;
- if (object) {
- QQmlData *ddata = QQmlData::get(object, false);
+ if (h->object) {
+ QQmlData *ddata = QQmlData::get(h->object, false);
if (ddata) {
- if (!object->parent() && !ddata->indestructible) {
+ if (!h->object->parent() && !ddata->indestructible) {
if (ddata && ddata->ownContext && ddata->context)
ddata->context->emitDestruction();
// This object is notionally destroyed now
ddata->isQueuedForDeletion = true;
if (lastCall)
- delete object;
+ delete h->object;
else
- object->deleteLater();
+ h->object->deleteLater();
}
}
}
@@ -1061,9 +1045,6 @@ void QObjectWrapper::destroyObject(bool lastCall)
DEFINE_OBJECT_VTABLE(QObjectWrapper);
-// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work
-// correctly in a worker thread
-
namespace {
template<typename A, typename B, typename C, typename D, typename E,
@@ -1729,24 +1710,23 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->object = object;
if (QQmlData *ddata = QQmlData::get(object))
method->d()->propertyCache = ddata->propertyCache;
method->d()->index = index;
- method->d()->valueTypeWrapper = Primitive::undefinedValue();
return method.asReturnedValue();
}
ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index)
{
Scope valueScope(scope);
- Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->allocObject<QObjectMethod>(scope));
method->d()->propertyCache = valueType->d()->propertyCache;
method->d()->index = index;
- method->d()->valueTypeWrapper = *valueType;
+ method->d()->valueTypeWrapper = valueType->d();
return method.asReturnedValue();
}
@@ -1815,8 +1795,8 @@ ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
ReturnedValue QObjectMethod::callInternal(CallData *callData) const
{
- Scope scope(engine());
- ScopedContext context(scope, scope.engine->currentContext());
+ ExecutionEngine *v4 = engine();
+ ExecutionContext *context = v4->currentContext;
if (d()->index == DestroyMethod)
return method_destroy(context, callData->args, callData->argc);
else if (d()->index == ToStringMethod)
@@ -1824,11 +1804,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
QQmlObjectOrGadget object(d()->object.data());
if (!d()->object) {
- Scoped<QQmlValueTypeWrapper> wrapper(scope, d()->valueTypeWrapper);
- if (!wrapper)
+ if (!d()->valueTypeWrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr);
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr);
}
QQmlPropertyData method;
@@ -1860,8 +1839,9 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
}
if (method.isV4Function()) {
+ Scope scope(v4);
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
- QQmlV4Function func(callData, rv, scope.engine);
+ QQmlV4Function func(callData, rv, v4);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
@@ -1871,31 +1851,46 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const
}
if (!method.isOverload()) {
- return CallPrecise(object, method, scope.engine, callData);
+ return CallPrecise(object, method, v4, callData);
} else {
- return CallOverloaded(object, method, scope.engine, callData, d()->propertyCache);
+ return CallOverloaded(object, method, v4, callData, d()->propertyCache);
}
}
void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
{
QObjectMethod::Data *This = static_cast<QObjectMethod::Data*>(that);
- This->valueTypeWrapper.mark(e);
+ if (This->valueTypeWrapper)
+ This->valueTypeWrapper->mark(e);
FunctionObject::markObjects(that, e);
}
DEFINE_OBJECT_VTABLE(QObjectMethod);
-Heap::QmlSignalHandler::QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex)
- : Heap::Object(engine)
- , object(object)
+Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex)
+ : object(object)
, signalIndex(signalIndex)
{
}
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
+void QmlSignalHandler::initProto(ExecutionEngine *engine)
+{
+ if (engine->signalHandlerPrototype()->d())
+ return;
+
+ Scope scope(engine);
+ ScopedObject o(scope, engine->newObject());
+ QV4::ScopedString connect(scope, engine->newIdentifier(QStringLiteral("connect")));
+ QV4::ScopedString disconnect(scope, engine->newIdentifier(QStringLiteral("disconnect")));
+ o->put(connect, QV4::ScopedValue(scope, engine->functionPrototype()->get(connect)));
+ o->put(disconnect, QV4::ScopedValue(scope, engine->functionPrototype()->get(disconnect)));
+
+ engine->jsObjects[QV4::ExecutionEngine::SignalHandlerProto] = o->d();
+}
+
void MultiplyWrappedQObjectMap::insert(QObject *key, Heap::Object *value)
{
QV4::WeakValue v;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index da24c81f40..1126013806 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -69,8 +69,10 @@ struct QObjectSlotDispatcher;
namespace Heap {
+struct QQmlValueTypeWrapper;
+
struct QObjectWrapper : Object {
- QObjectWrapper(QV4::ExecutionEngine *engine, QObject *object);
+ QObjectWrapper(QObject *object);
QPointer<QObject> object;
};
@@ -80,13 +82,13 @@ struct QObjectMethod : FunctionObject {
QQmlRefPointer<QQmlPropertyCache> propertyCache;
int index;
- Value valueTypeWrapper;
+ Pointer<QQmlValueTypeWrapper> valueTypeWrapper;
const QMetaObject *metaObject();
};
struct QmlSignalHandler : Object {
- QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex);
+ QmlSignalHandler(QObject *object, int signalIndex);
QPointer<QObject> object;
int signalIndex;
};
@@ -167,10 +169,13 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
struct QmlSignalHandler : public QV4::Object
{
V4_OBJECT2(QmlSignalHandler, QV4::Object)
+ V4_PROTOTYPE(signalHandlerPrototype)
V4_NEEDS_DESTROY
int signalIndex() const { return d()->signalIndex; }
QObject *object() const { return d()->object.data(); }
+
+ static void initProto(ExecutionEngine *v4);
};
class MultiplyWrappedQObjectMap : public QObject,
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 329e5d2c56..1839ff17ab 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -62,35 +62,30 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn
using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
-DEFINE_OBJECT_VTABLE(RegExpPrototype);
-Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+Heap::RegExpObject::RegExpObject()
{
- Scope scope(ic->engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(ic->engine, QString(), false, false);
+ o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false);
o->d()->global = false;
- o->init(ic->engine);
+ o->initProperties();
}
-Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype())
- , value(value->d())
+Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global)
+ : value(value->d())
, global(global)
{
- Scope scope(engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->init(engine);
+ o->initProperties();
}
// Converts a QRegExp to a JS RegExp.
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
-Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re)
- : Heap::Object(engine->emptyClass, engine->regExpPrototype())
+Heap::RegExpObject::RegExpObject(const QRegExp &re)
{
- value = 0;
global = false;
// Convert the pattern to a ECMAScript pattern.
@@ -130,26 +125,21 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re
pattern = ecmaPattern;
}
- Scope scope(engine);
+ Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = QV4::RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
+ o->d()->value = QV4::RegExp::create(scope.engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
- o->init(engine);
+ o->initProperties();
}
-void RegExpObject::init(ExecutionEngine *engine)
+void RegExpObject::initProperties()
{
- Scope scope(engine);
- ScopedObject protectThis(scope, this);
+ *propertyData(Index_LastIndex) = Primitive::fromInt32(0);
- ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex")));
- ScopedValue v(scope, Primitive::fromInt32(0));
- insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable);
- if (!this->value())
- return;
+ Q_ASSERT(value());
- QString p = this->value()->pattern;
+ QString p = value()->pattern;
if (p.isEmpty()) {
p = QStringLiteral("(?:)");
} else {
@@ -157,10 +147,10 @@ void RegExpObject::init(ExecutionEngine *engine)
p.replace('/', QLatin1String("\\/"));
}
- defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p)));
- defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global()));
- defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase));
- defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine));
+ *propertyData(Index_Source) = engine()->newString(p);
+ *propertyData(Index_Global) = Primitive::fromBoolean(global());
+ *propertyData(Index_IgnoreCase) = Primitive::fromBoolean(value()->ignoreCase);
+ *propertyData(Index_Multiline) = Primitive::fromBoolean(value()->multiLine);
}
@@ -172,10 +162,10 @@ void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
Object::markObjects(that, e);
}
-Property *RegExpObject::lastIndexProperty()
+Value *RegExpObject::lastIndexProperty()
{
Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
- return propertyAt(0);
+ return propertyData(0);
}
// Converts a JS RegExp to a QRegExp.
@@ -239,17 +229,16 @@ void Heap::RegExpCtor::clearLastMatch()
ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedContext ctx(scope, scope.engine->currentContext());
ScopedValue r(scope, callData->argument(0));
ScopedValue f(scope, callData->argument(1));
Scoped<RegExpObject> re(scope, r);
if (re) {
if (!f->isUndefined())
- return ctx->engine()->throwTypeError();
+ return scope.engine->throwTypeError();
Scoped<RegExp> regexp(scope, re->value());
- return Encode(ctx->d()->engine->newRegExpObject(regexp, re->global()));
+ return Encode(scope.engine->newRegExpObject(regexp, re->global()));
}
QString pattern;
@@ -274,16 +263,16 @@ ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
} else if (str.at(i) == QLatin1Char('m') && !multiLine) {
multiLine = true;
} else {
- return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
}
}
}
- Scoped<RegExp> regexp(scope, RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine));
+ Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine));
if (!regexp->isValid())
- return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid regular expression"));
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
- return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
+ return Encode(scope.engine->newRegExpObject(regexp, global));
}
ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
@@ -354,9 +343,9 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
return Encode::undefined();
QString s = arg->stringValue()->toQString();
- int offset = r->global() ? r->lastIndexProperty()->value.toInt32() : 0;
+ int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0;
if (offset < 0 || offset > s.length()) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
@@ -367,7 +356,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
@@ -383,8 +372,8 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- array->memberData()->data[Index_ArrayIndex] = Primitive::fromInt32(result);
- array->memberData()->data[Index_ArrayInput] = arg;
+ *array->propertyData(Index_ArrayIndex) = Primitive::fromInt32(result);
+ *array->propertyData(Index_ArrayInput) = arg;
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch = array;
@@ -393,7 +382,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- r->lastIndexProperty()->value = Primitive::fromInt32(matchOffsets[1]);
+ *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
return array.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 29d20614de..4f803df9c8 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -57,9 +57,9 @@ namespace QV4 {
namespace Heap {
struct RegExpObject : Object {
- RegExpObject(InternalClass *ic, QV4::Object *prototype);
- RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global);
- RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re);
+ RegExpObject();
+ RegExpObject(QV4::RegExp *value, bool global);
+ RegExpObject(const QRegExp &re);
Pointer<RegExp> value;
bool global;
@@ -74,16 +74,13 @@ struct RegExpCtor : FunctionObject {
void clearLastMatch();
};
-struct RegExpPrototype : RegExpObject
-{
- inline RegExpPrototype(ExecutionEngine *e);
-};
-
}
struct RegExpObject: Object {
V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
+ V4_INTERNALCLASS(regExpObjectClass)
+ V4_PROTOTYPE(regExpPrototype)
// needs to be compatible with the flags in qv4jsir_p.h
enum Flags {
@@ -93,6 +90,11 @@ struct RegExpObject: Object {
};
enum {
+ Index_LastIndex = 0,
+ Index_Source = 1,
+ Index_Global = 2,
+ Index_IgnoreCase = 3,
+ Index_Multiline = 4,
Index_ArrayIndex = Heap::ArrayObject::LengthPropertyIndex + 1,
Index_ArrayInput = Index_ArrayIndex + 1
};
@@ -100,9 +102,9 @@ struct RegExpObject: Object {
Heap::RegExp *value() const { return d()->value; }
bool global() const { return d()->global; }
- void init(ExecutionEngine *engine);
+ void initProperties();
- Property *lastIndexProperty();
+ Value *lastIndexProperty();
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
@@ -128,8 +130,6 @@ struct RegExpCtor: FunctionObject
struct RegExpPrototype: RegExpObject
{
- V4_OBJECT2(RegExpPrototype, RegExpObject)
-
void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_exec(CallContext *ctx);
@@ -145,11 +145,6 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_get_rightContext(CallContext *ctx);
};
-inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
- : RegExpObject(e->emptyClass, e->objectPrototype())
-{
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 9316223696..0d7a1851b8 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -268,10 +268,9 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
ReturnedValue Runtime::closure(ExecutionEngine *engine, int functionId)
{
- QV4::Function *clos = engine->currentContext()->compilationUnit->runtimeFunctions[functionId];
+ QV4::Function *clos = engine->current->compilationUnit->runtimeFunctions[functionId];
Q_ASSERT(clos);
- Scope scope(engine);
- return FunctionObject::createScriptFunction(ScopedContext(scope, engine->currentContext()), clos)->asReturnedValue();
+ return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue();
}
ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, const Value &index)
@@ -292,7 +291,7 @@ ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base,
ReturnedValue Runtime::deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
return deleteMemberString(engine, base, name);
}
@@ -308,9 +307,8 @@ ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value &
ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- return Encode(ctx->deleteProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return Encode(engine->currentContext->deleteProperty(name));
}
QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right)
@@ -566,7 +564,7 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left
void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object.toObject(engine));
if (!o)
return;
@@ -663,15 +661,14 @@ ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator)
void Runtime::setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->setProperty(name, value);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ engine->currentContext->setProperty(name, value);
}
ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject o(scope, object);
if (o)
@@ -691,9 +688,8 @@ ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object,
ReturnedValue Runtime::getActivationProperty(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- return ctx->getProperty(name);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ return engine->currentContext->getProperty(name);
}
#endif // V4_BOOTSTRAP
@@ -909,12 +905,12 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
ScopedFunctionObject o(scope, l->globalGetter(l, engine));
if (!o)
return engine->throwTypeError();
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval()))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
@@ -926,11 +922,10 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
{
Q_ASSERT(callData->thisObject.isUndefined());
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject base(scope);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedValue func(scope, ctx->getPropertyAndBase(name, base.getRef()));
+ ScopedValue func(scope, engine->currentContext->getPropertyAndBase(name, base.getRef()));
if (scope.engine->hasException)
return Encode::undefined();
@@ -980,7 +975,7 @@ ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int
ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject baseObject(scope, callData->thisObject);
if (!baseObject) {
Q_ASSERT(!callData->thisObject.isEmpty());
@@ -1006,7 +1001,7 @@ ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, Call
ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
Value v;
v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
@@ -1046,7 +1041,7 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index
Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
ScopedObject f(scope, l->globalGetter(l, engine));
if (!f)
return engine->throwTypeError();
@@ -1058,9 +1053,8 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index
ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedValue func(scope, ctx->getProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue func(scope, engine->currentContext->getProperty(name));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1084,7 +1078,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex,
{
Scope scope(engine);
ScopedObject thisObject(scope, callData->thisObject.toObject(engine));
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
if (scope.engine->hasException)
return Encode::undefined();
@@ -1097,7 +1091,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex,
ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = engine->currentContext()->lookups + index;
+ Lookup *l = engine->current->lookups + index;
Value v;
v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
@@ -1145,9 +1139,8 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ScopedValue prop(scope, ctx->getProperty(name));
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue prop(scope, engine->currentContext->getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
return Runtime::typeofValue(engine, prop);
@@ -1156,7 +1149,7 @@ QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject obj(scope, base.toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1175,14 +1168,6 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value &
return Runtime::typeofValue(engine, prop);
}
-void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
-{
- Scope scope(engine);
- ScopedObject obj(scope, o.toObject(engine));
- ScopedContext ctx(scope, engine->currentContext());
- ctx->newWithContext(obj);
-}
-
ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
{
if (!engine->hasException)
@@ -1190,45 +1175,47 @@ ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
return engine->catchException(0);
}
+/* The next three methods are a bit tricky. They can't open up a Scope, as that
+ * would mess up the pushing of the context.
+ *
+ * Instead the push/pop pair acts as a non local scope.
+ */
+void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
+{
+ engine->pushContext(engine->currentContext->newWithContext(o.toObject(engine)));
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
+}
+
void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex)
{
- Scope scope(engine);
- ScopedValue v(scope, engine->catchException(0));
- ScopedString exceptionVarName(scope, engine->currentContext()->compilationUnit->runtimeStrings[exceptionVarNameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->newCatchContext(exceptionVarName, v);
+ ExecutionContext *c = engine->currentContext;
+ engine->pushContext(c->newCatchContext(c->d()->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0)));
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
}
void Runtime::popScope(ExecutionEngine *engine)
{
+ Q_ASSERT(engine->jsStackTop = engine->currentContext + 2);
engine->popContext();
+ engine->jsStackTop -= 2;
}
void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- ctx->createMutableBinding(name, deletable);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
+ engine->currentContext->createMutableBinding(name, deletable);
}
ReturnedValue Runtime::arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
{
- Scope scope(engine);
- ScopedArrayObject a(scope, engine->newArrayObject());
-
- if (length) {
- a->arrayReserve(length);
- a->arrayPut(0, values, length);
- a->setArrayLengthUnchecked(length);
- }
- return a.asReturnedValue();
+ return engine->newArrayObject(values, length)->asReturnedValue();
}
ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
{
Scope scope(engine);
- QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId];
+ QV4::InternalClass *klass = engine->current->compilationUnit->runtimeClasses[classId];
ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
{
@@ -1238,7 +1225,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
}
for (uint i = 0; i < klass->size; ++i)
- o->memberData()->data[i] = *args++;
+ *o->propertyData(i) = *args++;
if (arrayValueCount > 0) {
ScopedValue entry(scope);
@@ -1269,10 +1256,10 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *
QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->currentContext()->type == Heap::ExecutionContext::Type_CallContext);
- Scope scope(engine);
- Scoped<CallContext> c(scope, static_cast<Heap::CallContext *>(engine->currentContext()));
- return (engine->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
+ Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext);
+ QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext);
+ QV4::InternalClass *ic = c->d()->strictMode ? engine->strictArgumentsObjectClass : engine->argumentsObjectClass;
+ return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), c)->asReturnedValue();
}
#endif // V4_BOOTSTRAP
@@ -1363,7 +1350,7 @@ ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine)
ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
+ return engine->current->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1459,13 +1446,13 @@ ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex)
{
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]);
return engine->qmlSingletonWrapper(name);
}
void Runtime::convertThisToObject(ExecutionEngine *engine)
{
- Value *t = &engine->currentContext()->callData->thisObject;
+ Value *t = &engine->current->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index e19aeaf882..0c79897015 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -54,18 +54,12 @@ struct ScopedValue;
struct Scope {
inline Scope(ExecutionContext *ctx)
: engine(ctx->d()->engine)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
{
mark = engine->jsStackTop;
}
explicit Scope(ExecutionEngine *e)
: engine(e)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
{
mark = engine->jsStackTop;
}
@@ -73,6 +67,7 @@ struct Scope {
~Scope() {
#ifndef QT_NO_DEBUG
Q_ASSERT(engine->jsStackTop >= mark);
+ Q_ASSERT(engine->currentContext < mark);
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
#ifdef V4_USE_VALGRIND
@@ -82,9 +77,6 @@ struct Scope {
}
Value *alloc(int nValues) {
-#ifndef QT_NO_DEBUG
- size += nValues;
-#endif
return engine->jsAlloca(nValues);
}
@@ -94,9 +86,6 @@ struct Scope {
ExecutionEngine *engine;
Value *mark;
-#ifndef QT_NO_DEBUG
- mutable int size;
-#endif
private:
Q_DISABLE_COPY(Scope)
@@ -108,18 +97,12 @@ struct ScopedValue
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(0);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
*ptr = v;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, Heap::Base *o)
@@ -129,27 +112,18 @@ struct ScopedValue
#if QT_POINTER_SIZE == 4
ptr->setTag(QV4::Value::Managed_Type);
#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(m->asReturnedValue());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(v);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
ScopedValue &operator=(const Value &v) {
@@ -213,18 +187,12 @@ struct Scoped
#if QT_POINTER_SIZE == 4
ptr->setTag(QV4::Value::Managed_Type);
#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(v.as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, Heap::Base *o)
{
@@ -232,69 +200,45 @@ struct Scoped
v = o;
ptr = scope.engine->jsStackTop++;
setPointer(v.as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(v.ptr->as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const Value &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(value_convert<T>(scope.engine, v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsStackTop++;
setPointer(v ? v->as<T>() : 0);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, T *t)
{
ptr = scope.engine->jsStackTop++;
setPointer(t);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, typename T::Data *t)
{
ptr = scope.engine->jsStackTop++;
*ptr = t;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(QV4::Value::fromReturnedValue(v).as<T>());
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
{
ptr = scope.engine->jsStackTop++;
ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
}
Scoped<T> &operator=(Heap::Base *o) {
@@ -414,29 +358,18 @@ struct ScopedProperty
struct ExecutionContextSaver
{
ExecutionEngine *engine;
- Value *savedContext;
+ ExecutionContext *savedContext;
- ExecutionContextSaver(Scope &scope, ExecutionContext *context)
- : engine(context->d()->engine)
- , savedContext(scope.alloc(1))
+ ExecutionContextSaver(Scope &scope)
+ : engine(scope.engine)
{
- savedContext->setM(context->d());
-#if QT_POINTER_SIZE == 4
- savedContext->setTag(QV4::Value::Managed_Type);
-#endif
- }
- ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
- : engine(context->engine)
- , savedContext(scope.alloc(1))
- {
- savedContext->setM(context);
-#if QT_POINTER_SIZE == 4
- savedContext->setTag(QV4::Value::Managed_Type);
-#endif
+ savedContext = engine->currentContext;
}
~ExecutionContextSaver()
{
- engine->current = static_cast<Heap::ExecutionContext *>(savedContext->heapObject());
+ Q_ASSERT(engine->jsStackTop > engine->currentContext);
+ engine->currentContext = savedContext;
+ engine->current = savedContext->d();
}
};
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 7067d10e22..7f2f22780e 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -59,11 +59,15 @@ namespace QV4 {
namespace Heap {
struct CompilationUnitHolder : Object {
- inline CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit);
+ inline CompilationUnitHolder(CompiledData::CompilationUnit *unit);
QQmlRefPointer<CompiledData::CompilationUnit> unit;
};
+struct QmlBindingWrapper : FunctionObject {
+ QmlBindingWrapper(QV4::QmlContext *scope, Function *f);
+};
+
}
struct CompilationUnitHolder : public Object
@@ -73,12 +77,17 @@ struct CompilationUnitHolder : public Object
};
inline
-Heap::CompilationUnitHolder::CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
- : Heap::Object(engine)
- , unit(unit)
+Heap::CompilationUnitHolder::CompilationUnitHolder(CompiledData::CompilationUnit *unit)
+ : unit(unit)
{
}
+struct QmlBindingWrapper : FunctionObject {
+ V4_OBJECT2(QmlBindingWrapper, FunctionObject)
+
+ static ReturnedValue call(const Managed *that, CallData *callData);
+};
+
}
QT_END_NAMESPACE
@@ -88,7 +97,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f)
: Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
{
Q_ASSERT(scope->inUse());
@@ -96,12 +105,6 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Functio
function = f;
if (function)
function->compilationUnit->addref();
-
- Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> protectThis(s, this);
-
- this->scope = scope->newQmlContext(qml);
- internalClass->engine->popContext();
}
ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
@@ -113,65 +116,33 @@ ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
+
QV4::Function *f = This->function();
if (!f)
return QV4::Encode::undefined();
- ScopedContext context(scope, v4->currentContext());
- Scoped<CallContext> ctx(scope, context->newCallContext(This, callData));
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(This, callData));
+ v4->pushContext(ctx);
- ExecutionContextSaver ctxSaver(scope, context);
ScopedValue result(scope, Q_V4_PROFILE(v4, f));
return result->asReturnedValue();
}
-static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
-{
- QV4::Scope scope(ctx);
- QV4::Scoped<CallContext> signalEmittingContext(scope, ctx->d()->parent.cast<Heap::CallContext>());
- Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext);
- return signalEmittingContext->argument(parameterIndex);
-}
-
-Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
-{
- ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
- QV4::Scope valueScope(engine);
- QV4::Scoped<QmlContextWrapper> qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
- ScopedContext global(valueScope, valueScope.engine->rootContext());
- QV4::Scoped<QmlContext> wrapperContext(valueScope, global->newQmlContext(qmlScopeObject));
- engine->popContext();
-
- if (!signalParameters.isEmpty()) {
- if (error)
- QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
- QV4::ScopedProperty p(valueScope);
- QV4::ScopedString s(valueScope);
- int index = 0;
- foreach (const QByteArray &param, signalParameters) {
- QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapperContext, index++, signalParameterGetter));
- p->setGetter(g);
- p->setSetter(0);
- s = engine->newString(QString::fromUtf8(param));
- qmlScopeObject->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
- }
- }
-
- QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
- return function->d();
-}
-
-Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit *compilationUnit)
+Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit)
: line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , qml(v4, qml), vmFunction(0), parseAsBinding(true)
+ , vmFunction(0), parseAsBinding(true)
{
+ if (qml)
+ qmlContext.set(v4, *qml);
+
parsed = true;
vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : 0;
if (vmFunction) {
Scope valueScope(v4);
- ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->allocObject<CompilationUnitHolder>(compilationUnit));
compilationUnitHolder.set(v4, holder);
}
}
@@ -242,7 +213,7 @@ void Script::parse()
isel->setUseFastLookups(false);
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
- ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->allocObject<CompilationUnitHolder>(compilationUnit));
compilationUnitHolder.set(v4, holder);
}
@@ -263,10 +234,10 @@ ReturnedValue Script::run()
QV4::ExecutionEngine *engine = scope->engine();
QV4::Scope valueScope(engine);
- if (qml.isUndefined()) {
+ if (qmlContext.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- ExecutionContextSaver ctxSaver(valueScope, scope);
+ ExecutionContextSaver ctxSaver(valueScope);
ContextStateSaver stateSaver(valueScope, scope);
scope->d()->strictMode = vmFunction->isStrict();
scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
@@ -274,8 +245,8 @@ ReturnedValue Script::run()
return Q_V4_PROFILE(engine, vmFunction);
} else {
- Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
+ Scoped<QmlContext> qml(valueScope, qmlContext.value());
+ ScopedFunctionObject f(valueScope, engine->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
@@ -352,15 +323,15 @@ ReturnedValue Script::qmlBinding()
parse();
ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- Scoped<QmlContextWrapper> qmlObj(valueScope, qml.value());
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
+ Scoped<QmlContext> qml(valueScope, qmlContext.value());
+ ScopedObject v(valueScope, v4->memoryManager->allocObject<QmlBindingWrapper>(qml, vmFunction));
return v.asReturnedValue();
}
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext)
{
QV4::Scope scope(engine);
- QV4::Script qmlScript(engine, scopeObject, script, QString());
+ QV4::Script qmlScript(engine, qmlContext, script, QString());
qmlScript.parse();
QV4::ScopedValue result(scope);
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index fad011f88a..63e8239342 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -36,6 +36,7 @@
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4functionobject_p.h"
+#include "qv4context_p.h"
#include <QQmlError>
@@ -85,32 +86,19 @@ struct ContextStateSaver {
}
};
-namespace Heap {
-struct QmlBindingWrapper : Heap::FunctionObject {
- QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::QmlContextWrapper *qml);
-};
-
-}
-
-struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
- V4_OBJECT2(QmlBindingWrapper, FunctionObject)
-
- static ReturnedValue call(const Managed *that, CallData *callData);
-
- static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
- const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
-};
-
struct Q_QML_EXPORT Script {
Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(scope), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
- Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionEngine *engine, QmlContext *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , qml(engine, qml), vmFunction(0), parseAsBinding(true) {}
- Script(ExecutionEngine *engine, Object *qml, CompiledData::CompilationUnit *compilationUnit);
+ , vmFunction(0), parseAsBinding(true) {
+ if (qml)
+ qmlContext.set(engine, *qml);
+ }
+ Script(ExecutionEngine *engine, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit);
~Script();
QString sourceFile;
int line;
@@ -120,7 +108,7 @@ struct Q_QML_EXPORT Script {
bool strictMode;
bool inheritContext;
bool parsed;
- QV4::PersistentValue qml;
+ QV4::PersistentValue qmlContext;
QV4::PersistentValue compilationUnitHolder;
Function *vmFunction;
bool parseAsBinding;
@@ -134,7 +122,7 @@ struct Q_QML_EXPORT Script {
static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source,
QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
- static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
+ static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext);
};
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 23bbcc60e1..36ee848d00 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -207,8 +207,8 @@ namespace Heap {
template <typename Container>
struct QQmlSequence : Object {
- QQmlSequence(QV4::ExecutionEngine *engine, const Container &container);
- QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex);
+ QQmlSequence(const Container &container);
+ QQmlSequence(QObject *object, int propertyIndex);
mutable Container container;
QPointer<QObject> object;
@@ -223,6 +223,7 @@ struct QQmlSequence : public QV4::Object
{
V4_OBJECT2(QQmlSequence<Container>, QV4::Object)
Q_MANAGED_TYPE(QmlSequence)
+ V4_PROTOTYPE(sequencePrototype)
V4_NEEDS_DESTROY
public:
@@ -543,26 +544,24 @@ public:
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype())
- , container(container)
+Heap::QQmlSequence<Container>::QQmlSequence(const Container &container)
+ : container(container)
, propertyIndex(-1)
, isReference(false)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
o->init();
}
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype())
- , object(object)
+Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex)
+ : object(object)
, propertyIndex(propertyIndex)
, isReference(true)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
o->loadReference();
@@ -644,7 +643,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(object, propertyIndex)); \
return obj.asReturnedValue(); \
} else
@@ -662,7 +661,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocObject<QQml##ElementTypeName##List>(v.value<SequenceType >())); \
return obj.asReturnedValue(); \
} else
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 01f94eeac6..bb1d3aeb69 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -246,15 +246,12 @@ void SparseArray::deleteNode(SparseArrayNode *z)
x->setParent(y->parent());
if (root == y)
root = x;
- else if (y->parent()->left == y) {
+ else if (y->parent()->left == y)
y->parent()->left = x;
- if (x)
- x->size_left += y->size_left;
- } else {
+ else
y->parent()->right = x;
- if (x)
- x->size_left += y->size_left;
- }
+ if (x && x == y->right)
+ x->size_left += y->size_left;
y->size_left = 0;
}
if (y->color() != SparseArrayNode::Red) {
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 9fbafa7ded..757ec6c6bf 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -67,25 +67,17 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(StringObject);
-Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype)
- : Heap::Object(ic, prototype)
+Heap::StringObject::StringObject()
{
Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
- string = ic->engine->newString();
-
- Scope scope(ic->engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(ic->engine->id_length(), Primitive::fromInt32(0));
+ string = internalClass->engine->id_empty()->d();
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
}
-Heap::StringObject::StringObject(ExecutionEngine *engine, const QV4::String *str)
- : Heap::Object(engine->emptyClass, engine->stringPrototype())
+Heap::StringObject::StringObject(const QV4::String *str)
{
string = str->d();
-
- Scope scope(engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(engine->id_length(), Primitive::fromUInt32(length()));
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
}
Heap::String *Heap::StringObject::getIndex(uint index) const
@@ -98,7 +90,7 @@ Heap::String *Heap::StringObject::getIndex(uint index) const
uint Heap::StringObject::length() const
{
- return string->toQString().length();
+ return string->len;
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
@@ -109,7 +101,7 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
Q_ASSERT(!!o);
if (index < static_cast<uint>(o->d()->string->toQString().length())) {
- if (v4->currentContext()->strictMode)
+ if (v4->current->strictMode)
v4->throwTypeError();
return false;
}
@@ -511,7 +503,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
if (regExp->global())
- regExp->lastIndexProperty()->value = Primitive::fromUInt32(0);
+ *regExp->lastIndexProperty() = Primitive::fromUInt32(0);
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index aa56a79bc3..86d77c726a 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -44,8 +44,12 @@ namespace QV4 {
namespace Heap {
struct StringObject : Object {
- StringObject(InternalClass *ic, QV4::Object *prototype);
- StringObject(ExecutionEngine *engine, const QV4::String *string);
+ enum {
+ LengthPropertyIndex = 0
+ };
+
+ StringObject();
+ StringObject(const QV4::String *string);
String *string;
Heap::String *getIndex(uint index) const;
@@ -61,6 +65,8 @@ struct StringCtor : FunctionObject {
struct StringObject: Object {
V4_OBJECT2(StringObject, Object)
Q_MANAGED_TYPE(StringObject)
+ V4_INTERNALCLASS(stringClass)
+ V4_PROTOTYPE(stringPrototype)
Heap::String *getIndex(uint index) const {
return d()->getIndex(index);
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index f06eeb08b9..b45bbb713c 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -216,11 +216,11 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
if (l != len)
scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array."));
uint byteLength = len * operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> buffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, byteLength));
+ Scoped<ArrayBuffer> buffer(scope, scope.engine->newArrayBuffer(byteLength));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = buffer->d();
array->d()->byteLength = byteLength;
array->d()->byteOffset = 0;
@@ -236,11 +236,11 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
uint byteLength = typedArray->d()->byteLength;
uint destByteLength = byteLength*destElementSize/srcElementSize;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, destByteLength));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(destByteLength));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = newBuffer->d();
array->d()->byteLength = destByteLength;
array->d()->byteOffset = 0;
@@ -290,7 +290,7 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
byteLength = (uint)l;
}
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = buffer->d();
array->d()->byteLength = byteLength;
array->d()->byteOffset = byteOffset;
@@ -305,11 +305,11 @@ ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
return scope.engine->throwTypeError();
uint elementSize = operations[that->d()->type].bytesPerElement;
- Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, l * elementSize));
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(l * elementSize));
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ Scoped<TypedArray > array(scope, TypedArray::create(scope.engine, that->d()->type));
array->d()->buffer = newBuffer->d();
array->d()->byteLength = l * elementSize;
array->d()->byteOffset = 0;
@@ -335,13 +335,17 @@ ReturnedValue TypedArrayCtor::call(const Managed *that, CallData *callData)
return construct(that, callData);
}
-Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t)
- : Heap::Object(e->emptyClass, e->typedArrayPrototype + t),
- type(operations + t),
+Heap::TypedArray::TypedArray(Type t)
+ : type(operations + t),
arrayType(t)
{
}
+Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
+{
+ return e->memoryManager->allocObject<TypedArray>(e->emptyClass, e->typedArrayPrototype + t, t);
+}
+
void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
{
static_cast<TypedArray::Data *>(that)->buffer->mark(e);
@@ -383,7 +387,7 @@ void TypedArray::putIndexed(Managed *m, uint index, const Value &value)
return;
reject:
- if (scope.engine->currentContext()->strictMode)
+ if (scope.engine->current->strictMode)
scope.engine->throwTypeError();
}
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 8e1090dcd2..74ee285da4 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -69,7 +69,7 @@ struct TypedArray : Object {
NTypes
};
- TypedArray(ExecutionEngine *e, Type t);
+ TypedArray(Type t);
const TypedArrayOperations *type;
Pointer<ArrayBuffer> buffer;
@@ -85,7 +85,7 @@ struct TypedArrayCtor : FunctionObject {
};
struct TypedArrayPrototype : Object {
- inline TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t);
+ inline TypedArrayPrototype(TypedArray::Type t);
TypedArray::Type type;
};
@@ -96,6 +96,8 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
{
V4_OBJECT2(TypedArray, Object)
+ static Heap::TypedArray *create(QV4::ExecutionEngine *e, Heap::TypedArray::Type t);
+
uint byteLength() const {
return d()->byteLength;
}
@@ -142,9 +144,8 @@ struct TypedArrayPrototype : Object
};
inline
-Heap::TypedArrayPrototype::TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t)
- : Heap::Object(e)
- , type(t)
+Heap::TypedArrayPrototype::TypedArrayPrototype(TypedArray::Type t)
+ : type(t)
{
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 6305e6dfbb..14094878d8 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -85,8 +85,8 @@ struct Q_QML_PRIVATE_EXPORT Value
Q_ALWAYS_INLINE quint64 val() const { return _val; }
Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; }
- Q_ALWAYS_INLINE void setValue(quint32 v) { setTagValue(tag(), v); }
- Q_ALWAYS_INLINE void setTag(quint32 t) { setTagValue(t, value()); }
+ Q_ALWAYS_INLINE void setValue(quint32 v) { memcpy(&_val, &v, 4); }
+ Q_ALWAYS_INLINE void setTag(quint32 t) { memcpy(4 + (quint8 *)&_val, &t, 4); }
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
static inline int valueOffset() { return 0; }
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index f9e26efe71..4609373cc9 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -43,12 +43,15 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
-Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value)
- : Heap::Object(engine->emptyClass, engine->variantPrototype())
+Heap::VariantObject::VariantObject()
+{
+}
+
+Heap::VariantObject::VariantObject(const QVariant &value)
{
data = value;
if (isScarce())
- engine->scarceResources.insert(this);
+ internalClass->engine->scarceResources.insert(this);
}
bool VariantObject::Data::isScarce() const
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index b19f12bb98..4680912354 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -60,10 +60,8 @@ namespace Heap {
struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
{
- VariantObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
- {}
- VariantObject(QV4::ExecutionEngine *engine, const QVariant &value);
+ VariantObject();
+ VariantObject(const QVariant &value);
~VariantObject() {
if (isScarce())
node.remove();
@@ -77,6 +75,7 @@ struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
struct VariantObject : Object
{
V4_OBJECT2(VariantObject, Object)
+ V4_PROTOTYPE(variantPrototype)
V4_NEEDS_DESTROY
void addVmePropertyReference();
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 0edd7378a7..68f996c4c7 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -375,8 +375,8 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
const uchar *exceptionHandler = 0;
QV4::Scope scope(engine);
- QV4::ScopedContext context(scope, engine->currentContext());
- engine->currentContext()->lineNumber = -1;
+ QV4::ExecutionContext *context = engine->currentContext;
+ engine->current->lineNumber = -1;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
@@ -650,18 +650,18 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
Runtime::pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
- context = engine->currentContext();
+ context = engine->currentContext;
MOTH_END_INSTR(CallBuiltinPushCatchScope)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
Runtime::pushWithScope(VALUE(instr.arg), engine);
- context = engine->currentContext();
+ context = engine->currentContext;
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
Runtime::popScope(engine);
- context = engine->currentContext();
+ context = engine->currentContext;
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
@@ -889,7 +889,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
- engine->currentContext()->lineNumber = instr.lineNumber;
+ engine->current->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
@@ -898,7 +898,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
- engine->currentContext()->lineNumber = instr.lineNumber;
+ engine->current->lineNumber = instr.lineNumber;
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
MOTH_END_INSTR(Line)
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index b880c9c8d5..0887e43441 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -64,6 +64,8 @@
#include <pthread_np.h>
#endif
+#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT (std::size_t)128*1024
+
using namespace WTF;
QT_BEGIN_NAMESPACE
@@ -124,7 +126,7 @@ struct MemoryManager::Data
, maxShift(6)
, maxChunkSize(32*1024)
, unmanagedHeapSize(0)
- , unmanagedHeapSizeGCLimit(64 * 1024)
+ , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
, largeItems(0)
, totalLargeItemsAllocated(0)
{
@@ -219,7 +221,8 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
} // namespace
MemoryManager::MemoryManager(ExecutionEngine *engine)
- : m_d(new Data)
+ : engine(engine)
+ , m_d(new Data)
, m_persistentValues(new PersistentValueStorage(engine))
, m_weakValues(new PersistentValueStorage(engine))
{
@@ -246,13 +249,12 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) {
runGC();
- if (m_d->unmanagedHeapSizeGCLimit <= m_d->unmanagedHeapSize)
+ if (3*m_d->unmanagedHeapSizeGCLimit <= 4*m_d->unmanagedHeapSize)
+ // more than 75% full, raise limit
m_d->unmanagedHeapSizeGCLimit = std::max(m_d->unmanagedHeapSizeGCLimit, m_d->unmanagedHeapSize) * 2;
else if (m_d->unmanagedHeapSize * 4 <= m_d->unmanagedHeapSizeGCLimit)
- m_d->unmanagedHeapSizeGCLimit /= 2;
- else if (m_d->unmanagedHeapSizeGCLimit - m_d->unmanagedHeapSize < 5 * unmanagedSize)
- // try preventing running the GC all the time when we're just below the threshold limit and manage to collect just enough to do this one allocation
- m_d->unmanagedHeapSizeGCLimit += std::max(std::size_t(8 * 1024), 5 * unmanagedSize);
+ // less than 25% full, lower limit
+ m_d->unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, m_d->unmanagedHeapSizeGCLimit/2);
didGCRun = true;
}
@@ -265,7 +267,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
// we use malloc for this
MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(
- malloc(Q_V4_PROFILE_ALLOC(m_d->engine, size + sizeof(MemoryManager::Data::LargeItem),
+ malloc(Q_V4_PROFILE_ALLOC(engine, size + sizeof(MemoryManager::Data::LargeItem),
Profiling::LargeItem)));
memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
item->next = m_d->largeItems;
@@ -301,7 +303,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
PageAllocation allocation = PageAllocation::allocate(
- Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
+ Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
m_d->heapChunks.append(allocation);
@@ -335,7 +337,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_ALLOC(this, m, size);
#endif
- Q_V4_PROFILE_ALLOC(m_d->engine, size, Profiling::SmallItem);
+ Q_V4_PROFILE_ALLOC(engine, size, Profiling::SmallItem);
++m_d->allocCount[pos];
++m_d->totalAlloc;
@@ -356,14 +358,14 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
void MemoryManager::mark()
{
- Value *markBase = m_d->engine->jsStackTop;
-
- m_d->engine->markObjects();
+ Value *markBase = engine->jsStackTop;
- m_persistentValues->mark(m_d->engine);
+ engine->markObjects();
collectFromJSStack();
+ m_persistentValues->mark(engine);
+
// Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
// keeps all of its children alive in JavaScript.
@@ -391,13 +393,13 @@ void MemoryManager::mark()
}
if (keepAlive)
- qobjectWrapper->mark(m_d->engine);
+ qobjectWrapper->mark(engine);
- if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
- drainMarkStack(m_d->engine, markBase);
+ if (engine->jsStackTop >= engine->jsStackLimit)
+ drainMarkStack(engine, markBase);
}
- drainMarkStack(m_d->engine, markBase);
+ drainMarkStack(engine, markBase);
}
void MemoryManager::sweep(bool lastSweep)
@@ -416,7 +418,7 @@ void MemoryManager::sweep(bool lastSweep)
(*it) = Primitive::undefinedValue();
}
- if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
+ if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) {
for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
if (!it.value().isNullOrUndefined())
it = multiplyWrappedQObjects->erase(it);
@@ -432,7 +434,7 @@ void MemoryManager::sweep(bool lastSweep)
for (int i = 0; i < m_d->heapChunks.size(); ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
- chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], m_d->engine, &m_d->unmanagedHeapSize);
+ chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
}
QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
@@ -444,7 +446,7 @@ void MemoryManager::sweep(bool lastSweep)
// Release that chunk if it could have been spared since the last GC run without any difference.
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
- Q_V4_PROFILE_DEALLOC(m_d->engine, 0, chunkIter->size(), Profiling::HeapPage);
+ Q_V4_PROFILE_DEALLOC(engine, 0, chunkIter->size(), Profiling::HeapPage);
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_FREE(this, header);
#endif
@@ -476,17 +478,17 @@ void MemoryManager::sweep(bool lastSweep)
m->vtable()->destroy(m);
*last = i->next;
- free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
+ free(Q_V4_PROFILE_DEALLOC(engine, i, i->size + sizeof(Data::LargeItem),
Profiling::LargeItem));
i = *last;
}
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
- Heap::ExecutionContext *ctx = engine()->current;
+ QV4::ExecutionContext *ctx = engine->currentContext;
while (ctx) {
- ctx->clearMarkBit();
- ctx = ctx->parent;
+ ctx->d()->clearMarkBit();
+ ctx = engine->parentContext(ctx);
}
}
}
@@ -520,9 +522,11 @@ void MemoryManager::runGC()
int markTime = t.elapsed();
t.restart();
const size_t usedBefore = getUsedMem();
+ const size_t largeItemsBefore = getLargeItemsMem();
int chunksBefore = m_d->heapChunks.size();
sweep();
const size_t usedAfter = getUsedMem();
+ const size_t largeItemsAfter = getLargeItemsMem();
int sweepTime = t.elapsed();
qDebug() << "========== GC ==========";
@@ -533,6 +537,9 @@ void MemoryManager::runGC()
qDebug() << "Used memory after GC:" << usedAfter;
qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size());
+ qDebug() << "Large item memory before GC:" << largeItemsBefore;
+ qDebug() << "Large item memory after GC:" << largeItemsAfter;
+ qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
qDebug() << "======== End GC ========";
}
@@ -589,10 +596,7 @@ MemoryManager::~MemoryManager()
#endif
}
-ExecutionEngine *MemoryManager::engine() const
-{
- return m_d->engine;
-}
+
void MemoryManager::dumpStats() const
{
@@ -622,13 +626,13 @@ void MemoryManager::willAllocate(std::size_t size)
void MemoryManager::collectFromJSStack() const
{
- Value *v = m_d->engine->jsStackBase;
- Value *top = m_d->engine->jsStackTop;
+ Value *v = engine->jsStackBase;
+ Value *top = engine->jsStackTop;
while (v < top) {
Managed *m = v->as<Managed>();
if (m && m->inUse())
// Skip pointers to already freed objects, they are bogus as well
- m->mark(m_d->engine);
+ m->mark(engine);
++v;
}
}
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index c01866ff11..c77d5e503d 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -37,6 +37,7 @@
#include <private/qv4global_p.h>
#include <private/qv4value_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4object_p.h>
//#define DETAILED_MM_STATS
@@ -91,10 +92,149 @@ public:
return static_cast<typename ManagedType::Data *>(o);
}
+ template <typename ObjectType>
+ typename ObjectType::Data *allocateObject(InternalClass *ic)
+ {
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ o->internalClass = ic;
+ o->inlineMemberSize = ic->size;
+ o->inlineMemberOffset = size/sizeof(Value);
+ return o;
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocateObject()
+ {
+ InternalClass *ic = ObjectType::defaultInternalClass(engine);
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ typename ObjectType::Data *o = allocManaged<ObjectType>(size + ic->size*sizeof(Value));
+ Object *prototype = ObjectType::defaultPrototype(engine);
+ o->internalClass = ic;
+ o->prototype = prototype->d();
+ o->inlineMemberSize = ic->size;
+ o->inlineMemberOffset = size/sizeof(Value);
+ return o;
+ }
+
+ template <typename ManagedType, typename Arg1>
+ typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
+ (void)new (t->d()) typename ManagedType::Data(this, arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic));
+ t->d()->prototype = prototype->d();
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject()
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(Arg1 arg1)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ typename ObjectType::Data *allocObject(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ Scope scope(engine);
+ Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4);
+ return t->d();
+ }
+
+
template <typename ManagedType>
typename ManagedType::Data *alloc()
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data();
return t->d();
@@ -103,25 +243,16 @@ public:
template <typename ManagedType, typename Arg1>
typename ManagedType::Data *alloc(Arg1 arg1)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1);
return t->d();
}
- template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
- {
- Scope scope(engine());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
- (void)new (t->d()) typename ManagedType::Data(this, arg1);
- return t->d();
- }
-
template <typename ManagedType, typename Arg1, typename Arg2>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2);
return t->d();
@@ -130,7 +261,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
return t->d();
@@ -139,7 +270,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
return t->d();
@@ -148,7 +279,7 @@ public:
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
{
- Scope scope(engine());
+ Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
return t->d();
@@ -158,8 +289,6 @@ public:
void setGCBlocked(bool blockGC);
void runGC();
- ExecutionEngine *engine() const;
-
void dumpStats() const;
size_t getUsedMem() const;
@@ -182,9 +311,9 @@ private:
void mark();
void sweep(bool lastSweep = false);
-protected:
- QScopedPointer<Data> m_d;
public:
+ QV4::ExecutionEngine *engine;
+ QScopedPointer<Data> m_d;
PersistentValueStorage *m_persistentValues;
PersistentValueStorage *m_weakValues;
};
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 3613c17242..f8b737a62a 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -90,7 +90,7 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
if (runtimeFunction) {
- m_function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
+ m_function.set(v4, QV4::FunctionObject::createQmlFunction(ctxtdata, scopeObject(), runtimeFunction));
} else {
QString code = scriptPrivate->script;
createQmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber);
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index ff5f36bd9c..decffaf2fa 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -124,7 +124,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
QString error;
QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
- m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
+ m_function.set(engine, QV4::FunctionObject::createQmlFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
m_function.clear();
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index d62aada9c6..be482b4639 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -42,7 +42,6 @@
#include "qqml.h"
#include "qqmlengine.h"
#include "qqmlbinding_p.h"
-#include "qqmlglobal_p.h"
#include <private/qqmldebugconnector_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
#include "qqmlincubator.h"
@@ -1060,11 +1059,10 @@ namespace QV4 {
namespace Heap {
struct QmlIncubatorObject : Object {
- QmlIncubatorObject(QV4::ExecutionEngine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
QScopedPointer<QQmlComponentIncubator> incubator;
QPointer<QObject> parent;
QV4::Value valuemap;
- QV4::Value qmlGlobal;
QV4::Value statusChanged;
};
@@ -1376,14 +1374,12 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QQmlComponentExtension *e = componentExtension(args->v4engine());
- QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->alloc<QV4::QmlIncubatorObject>(args->v4engine(), mode));
+ QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocObject<QV4::QmlIncubatorObject>(mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
r->setPrototype(p);
- if (!valuemap->isUndefined()) {
+ if (!valuemap->isUndefined())
r->d()->valuemap = valuemap;
- r->d()->qmlGlobal = args->qmlGlobal();
- }
r->d()->parent = parent;
QQmlIncubator *incubator = r->d()->incubator.data();
@@ -1481,10 +1477,8 @@ QQmlComponentExtension::~QQmlComponentExtension()
{
}
-QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(ExecutionEngine *engine, QQmlIncubator::IncubationMode m)
- : QV4::Heap::Object(engine)
- , valuemap(QV4::Primitive::undefinedValue())
- , qmlGlobal(QV4::Primitive::undefinedValue())
+QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m)
+ : valuemap(QV4::Primitive::undefinedValue())
, statusChanged(QV4::Primitive::undefinedValue())
{
incubator.reset(new QQmlComponentIncubator(this, m));
@@ -1506,7 +1500,6 @@ void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionE
{
QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that);
o->valuemap.mark(e);
- o->qmlGlobal.mark(e);
o->statusChanged.mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 99a5fe56ce..0d84c3bb64 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -54,9 +54,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlContextWrapper);
-Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
- : Heap::Object(engine)
- , readOnly(true)
+Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext)
+ : readOnly(true)
, ownsContext(ownsContext)
, isNullWrapper(false)
, context(context)
@@ -74,7 +73,7 @@ ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *
{
Scope valueScope(v4);
- Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->alloc<QmlContextWrapper>(v4, ctxt, scope));
+ Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->allocObject<QmlContextWrapper>(ctxt, scope));
return w.asReturnedValue();
}
@@ -88,7 +87,7 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
context->isInternal = true;
context->isJSContext = true;
- Scoped<QmlContextWrapper> w(scope, v4->memoryManager->alloc<QmlContextWrapper>(v4, context, (QObject*)0, true));
+ Scoped<QmlContextWrapper> w(scope, v4->memoryManager->allocObject<QmlContextWrapper>(context, (QObject*)0, true));
w->d()->isNullWrapper = true;
return w.asReturnedValue();
}
@@ -240,7 +239,7 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
uint member = wrapper->internalClass()->find(name);
if (member < UINT_MAX) {
- wrapper->putValue(wrapper->propertyAt(member), wrapper->internalClass()->propertyData[member], value);
+ wrapper->putValue(member, value);
return;
}
@@ -248,7 +247,7 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value)
if (wrapper && wrapper->d()->readOnly) {
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
- ScopedString e(scope, v4->currentContext()->engine->newString(error));
+ ScopedString e(scope, v4->newString(error));
v4->throwError(e);
return;
}
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 192df9aed6..9dd71b708f 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -66,7 +66,7 @@ struct QmlContextWrapper;
namespace Heap {
struct QmlContextWrapper : Object {
- QmlContextWrapper(ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
+ QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
~QmlContextWrapper();
bool readOnly;
bool ownsContext;
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index ebca9d2718..517f8d42ed 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -34,6 +34,7 @@
#include "qqmlcustomparser_p.h"
#include "qqmlcompiler_p.h"
+#include <private/qqmltypecompiler_p.h>
#include <QtCore/qdebug.h>
@@ -140,7 +141,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
type = result.type;
}
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
}
const QMetaObject *mo = StaticQtMetaObject::get();
@@ -159,34 +160,8 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
*/
const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
{
- return compiler->resolveType(name);
-}
-
-int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
-{
- Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
- *ok = false;
-
- if (scope != QLatin1String("Qt")) {
- QQmlType *type = 0;
- imports().resolveType(scope, &type, 0, 0, 0);
- return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
- }
-
- const QMetaObject *mo = StaticQtMetaObject::get();
- int i = mo->enumeratorCount();
- while (i--) {
- int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
- if (*ok)
- return v;
- }
- return -1;
-}
-
-const QMetaObject *QQmlCustomParserCompilerBackend::resolveType(const QString &name) const
-{
QQmlType *qmltype = 0;
- if (!imports().resolveType(name, &qmltype, 0, 0, 0))
+ if (!validator->imports().resolveType(name, &qmltype, 0, 0, 0))
return 0;
if (!qmltype)
return 0;
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 88282b1bbc..8bdc73fab1 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -55,15 +55,8 @@
QT_BEGIN_NAMESPACE
class QQmlCompiledData;
-
-struct QQmlCustomParserCompilerBackend
-{
- virtual ~QQmlCustomParserCompilerBackend() {}
- virtual const QQmlImports &imports() const = 0;
-
- int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const;
- const QMetaObject *resolveType(const QString& name) const;
-};
+class QQmlPropertyValidator;
+class QQmlEnginePrivate;
class Q_QML_PRIVATE_EXPORT QQmlCustomParser
{
@@ -75,8 +68,8 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
- QQmlCustomParser() : compiler(0), m_flags(NoFlag) {}
- QQmlCustomParser(Flags f) : compiler(0), m_flags(f) {}
+ QQmlCustomParser() : engine(0), validator(0), m_flags(NoFlag) {}
+ QQmlCustomParser(Flags f) : engine(0), validator(0), m_flags(f) {}
virtual ~QQmlCustomParser() {}
void clearErrors();
@@ -100,7 +93,8 @@ protected:
private:
QList<QQmlError> exceptions;
- const QQmlCustomParserCompilerBackend *compiler;
+ QQmlEnginePrivate *engine;
+ const QQmlPropertyValidator *validator;
Flags m_flags;
QBiPointer<const QQmlImports, QQmlTypeNameCache> imports;
friend class QQmlPropertyValidator;
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 332b99ee8f..e9700712e9 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -69,7 +69,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFu
{
expressionFunctionValid = true;
QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
- m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
+ m_function.set(engine, QV4::FunctionObject::createQmlFunction(ctxt, me, runtimeFunction));
QQmlJavaScriptExpression::setContext(ctxt);
setScopeObject(me);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 76583846f9..d0d14d9416 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1659,8 +1659,6 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
\header \li Platform \li Valid suffixes
\row \li Windows \li \c .dll
\row \li Unix/Linux \li \c .so
- \row \li AIX \li \c .a
- \row \li HP-UX \li \c .sl, \c .so (HP-UXi)
\row \li OS X \li \c .dylib, \c .bundle, \c .so
\endtable
@@ -1677,9 +1675,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
<< QLatin1String("d.dll") // try a qmake-style debug build first
# endif
<< QLatin1String(".dll"));
-#else
-
-# if defined(Q_OS_DARWIN)
+#elif defined(Q_OS_DARWIN)
return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
QStringList()
@@ -1693,31 +1689,8 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
<< QLatin1String(".so")
<< QLatin1String(".bundle"),
QLatin1String("lib"));
-# else // Generic Unix
- QStringList validSuffixList;
-
-# if defined(Q_OS_HPUX)
-/*
- See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
- "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
- the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
- */
- validSuffixList << QLatin1String(".sl");
-# if defined __ia64
- validSuffixList << QLatin1String(".so");
-# endif
-# elif defined(Q_OS_AIX)
- validSuffixList << QLatin1String(".a") << QLatin1String(".so");
-# elif defined(Q_OS_UNIX)
- validSuffixList << QLatin1String(".so");
-# endif
-
- // Examples of valid library names:
- // libfoo.so
-
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
-# endif
-
+# else // Unix
+ return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".so"), QLatin1String("lib"));
#endif
}
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index b9f96a724c..7a801032d3 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -109,34 +109,8 @@ QQmlInfo::~QQmlInfo()
if (object) {
engine = qmlEngine(d->object);
- QString typeName;
- QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
- if (type) {
- typeName = type->qmlTypeName();
- int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
- if (lastSlash != -1)
- typeName = typeName.mid(lastSlash+1);
- } else {
- typeName = QString::fromUtf8(object->metaObject()->className());
- int marker = typeName.indexOf(QLatin1String("_QMLTYPE_"));
- if (marker != -1)
- typeName = typeName.left(marker);
-
- marker = typeName.indexOf(QLatin1String("_QML_"));
- if (marker != -1) {
- typeName = typeName.left(marker);
- typeName += QLatin1Char('*');
- type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
- if (type) {
- typeName = type->qmlTypeName();
- int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
- if (lastSlash != -1)
- typeName = typeName.mid(lastSlash+1);
- }
- }
- }
- d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": "));
+ d->buffer.prepend(QLatin1String("QML ") + QQmlMetaType::prettyTypeName(object) + QLatin1String(": "));
QQmlData *ddata = QQmlData::get(object, false);
if (ddata && ddata->outerContext) {
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 967a7e75d7..5938ebf5d7 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -365,8 +365,8 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
- QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, scopeObject));
- QV4::Script script(v4, qmlScopeObject, code, filename, line);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, scopeObject));
+ QV4::Script script(v4, qmlContext, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
@@ -395,8 +395,8 @@ void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
- QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, qmlScope));
- QV4::Script script(v4, qmlScopeObject, code, filename, line);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, qmlScope));
+ QV4::Script script(v4, qmlContext, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index d09f4df54c..942f4f79e7 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -45,10 +45,9 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlListWrapper);
-Heap::QmlListWrapper::QmlListWrapper(ExecutionEngine *engine)
- : Heap::Object(engine)
+Heap::QmlListWrapper::QmlListWrapper()
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
}
@@ -64,7 +63,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine));
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
r->d()->object = object;
r->d()->propertyType = propType;
void *args[] = { &r->d()->property, 0 };
@@ -76,7 +75,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp
{
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine));
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
r->d()->object = prop.object;
r->d()->property = prop;
r->d()->propertyType = propType;
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index ff006d4302..6df3d83b2e 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -62,7 +62,7 @@ namespace QV4 {
namespace Heap {
struct QmlListWrapper : Object {
- QmlListWrapper(ExecutionEngine *engine);
+ QmlListWrapper();
~QmlListWrapper();
QPointer<QObject> object;
QQmlListProperty<QObject> property;
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 7f49798da6..af7b394a1b 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -806,7 +806,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
{
QV4::Scope scope(v4);
QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
- QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->alloc<QQmlLocaleData>(v4));
+ QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>());
wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
wrapper->setPrototype(p);
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index cb9fe9bbef..3d2ed307d1 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -125,7 +125,7 @@ namespace QV4 {
namespace Heap {
struct QQmlLocaleData : Object {
- inline QQmlLocaleData(ExecutionEngine *engine);
+ inline QQmlLocaleData() {}
QLocale locale;
};
@@ -175,11 +175,6 @@ struct QQmlLocaleData : public QV4::Object
static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx);
};
-Heap::QQmlLocaleData::QQmlLocaleData(ExecutionEngine *engine)
- : Heap::Object(engine)
-{
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index fbb21f4562..04c001d305 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -38,6 +38,7 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qhashedstring_p.h>
#include <private/qqmlimport_p.h>
+#include <private/qqmlcompiler_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -217,12 +218,10 @@ public:
void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(e->handle());
+ v4->pushGlobalContext();
if (scriptCallback && scriptApi(e).isUndefined()) {
- v4->pushGlobalContext();
setScriptApi(e, scriptCallback(e, e));
- v4->popContext();
} else if (qobjectCallback && !qobjectApi(e)) {
- v4->pushGlobalContext();
QObject *o = qobjectCallback(e, e);
setQObjectApi(e, o);
if (!o) {
@@ -230,14 +229,12 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
}
// if this object can use a property cache, create it now
QQmlData::ensurePropertyCache(e, o);
- v4->popContext();
} else if (!url.isEmpty() && !qobjectApi(e)) {
- v4->pushGlobalContext();
QQmlComponent component(e, url, QQmlComponent::PreferSynchronous);
QObject *o = component.create();
setQObjectApi(e, o);
- v4->popContext();
}
+ v4->popContext();
}
void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e)
@@ -477,6 +474,23 @@ QQmlType *QQmlType::superType() const
return d->superType;
}
+int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+{
+ Q_ASSERT(isComposite());
+ *ok = false;
+ if (!engine)
+ return -1;
+ QQmlTypeData *td = engine->typeLoader.getType(sourceUrl());
+ if (!td || !td->isComplete())
+ return -1;
+ QQmlCompiledData *cd = td->compiledData();
+ const QMetaObject *mo = cd->rootPropertyCache->firstCppMetaObject();
+ QQmlType *type = QQmlMetaType::qmlType(mo);
+ if (!type)
+ return -1;
+ return type->enumValue(engine, name, ok);
+}
+
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
{
@@ -911,9 +925,11 @@ QUrl QQmlType::sourceUrl() const
return QUrl();
}
-int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
+ if (isComposite())
+ return resolveCompositeEnumValue(engine, name.toString(), ok);
*ok = true;
d->initEnums();
@@ -926,9 +942,11 @@ int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const
return -1;
}
-int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
+ if (isComposite())
+ return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
*ok = true;
d->initEnums();
@@ -941,9 +959,11 @@ int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const
return -1;
}
-int QQmlType::enumValue(const QV4::String *name, bool *ok) const
+int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
Q_ASSERT(ok);
+ if (isComposite())
+ return resolveCompositeEnumValue(engine, name->toQString(), ok);
*ok = true;
d->initEnums();
@@ -1888,4 +1908,43 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const
return 0;
}
+/*!
+ Returns the pretty QML type name (e.g. 'Item' instead of 'QtQuickItem') for the given object.
+ */
+QString QQmlMetaType::prettyTypeName(const QObject *object)
+{
+ QString typeName;
+
+ if (!object)
+ return typeName;
+
+ const QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
+ if (type) {
+ typeName = type->qmlTypeName();
+ const int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash != -1)
+ typeName = typeName.mid(lastSlash + 1);
+ } else {
+ typeName = QString::fromUtf8(object->metaObject()->className());
+ int marker = typeName.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ typeName = typeName.left(marker);
+
+ marker = typeName.indexOf(QLatin1String("_QML_"));
+ if (marker != -1) {
+ typeName = typeName.left(marker);
+ typeName += QLatin1Char('*');
+ type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
+ if (type) {
+ typeName = type->qmlTypeName();
+ const int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash != -1)
+ typeName = typeName.mid(lastSlash + 1);
+ }
+ }
+ }
+
+ return typeName;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 61a6567f1d..40765d461a 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE
class QQmlType;
class QQmlEngine;
+class QQmlEnginePrivate;
class QQmlCustomParser;
class QQmlTypePrivate;
class QQmlTypeModule;
@@ -122,6 +123,8 @@ public:
static QStringList typeRegistrationFailures();
static QMutex *typeRegistrationLock();
+
+ static QString prettyTypeName(const QObject *object);
};
struct QQmlMetaTypeData;
@@ -204,11 +207,12 @@ public:
QUrl sourceUrl() const;
- int enumValue(const QHashedStringRef &, bool *ok) const;
- int enumValue(const QHashedCStringRef &, bool *ok) const;
- int enumValue(const QV4::String *, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const;
+ int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const;
private:
QQmlType *superType() const;
+ int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const;
friend class QQmlTypePrivate;
friend struct QQmlMetaTypeData;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 0e7ce7fb7e..765437b423 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -185,9 +185,10 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (subComponentIndex == -1 && compiledData->scripts.count()) {
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
context->importedScripts.set(v4, scripts);
+ QV4::ScopedValue v(scope);
for (int i = 0; i < compiledData->scripts.count(); ++i) {
QQmlScriptData *s = compiledData->scripts.at(i);
- scripts->putIndexed(i, *s->scriptValueForContext(context).valueRef());
+ scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
context->importedScripts = sharedState->creationContext->importedScripts;
@@ -988,13 +989,9 @@ void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject *
QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
{
- if (!_qmlContext->objectValue()) {
- QV4::Scope valueScope(v4);
- QV4::Scoped<QV4::QmlContextWrapper> qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
- QV4::ScopedContext global(valueScope, v4->rootContext());
- _qmlContext->setM(global->newQmlContext(qmlScope));
- v4->popContext();
- }
+ if (!_qmlContext->objectValue())
+ _qmlContext->setM(v4->rootContext()->newQmlContext(context, _scopeObject));
+
return _qmlContext->d();
}
@@ -1106,6 +1103,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (customParser) {
QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index);
if (customParserBindings != compiledData->customParserBindings.constEnd()) {
+ customParser->engine = QQmlEnginePrivate::get(engine);
customParser->imports = compiledData->importCache;
QList<const QV4::CompiledData::Binding *> bindings;
@@ -1115,6 +1113,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
bindings << obj->bindingTable() + i;
customParser->applyBindings(instance, compiledData, bindings);
+ customParser->engine = 0;
customParser->imports = (QQmlTypeNameCache*)0;
bindingsToSkip = *customParserBindings;
}
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index c1120b4542..d3f7070528 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -50,6 +50,7 @@
#include "qqmlvaluetypeproxybinding_p.h"
#include <private/qjsvalue_p.h>
#include <private/qv4functionobject_p.h>
+#include <private/qv4runtime_p.h>
#include <QStringList>
#include <private/qmetaobject_p.h>
@@ -1350,7 +1351,12 @@ bool QQmlPropertyPrivate::write(QObject *object,
if (!ok) {
v = value;
- if (v.convert(propertyType)) {
+ if (variantType == QVariant::Double && propertyType == QVariant::String) {
+ QString number;
+ QV4::RuntimeHelpers::numberToString(&number, v.toDouble());
+ v = number;
+ ok = true;
+ } else if (v.convert(propertyType)) {
ok = true;
} else if (v.isValid() && value.isNull()) {
// For historical reasons converting a null QVariant to another type will do the trick
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index eb65f732dd..270c28c399 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2471,12 +2471,10 @@ void QQmlScriptData::initialize(QQmlEngine *engine)
addref();
}
-QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
+QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
{
if (m_loaded)
- return m_value;
-
- QV4::PersistentValue rv;
+ return m_value.value();
Q_ASSERT(parentCtxt && parentCtxt->engine);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
@@ -2526,8 +2524,9 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
} else {
scriptsArray = ctxt->importedScripts.valueRef();
}
+ QV4::ScopedValue v(scope);
for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->putIndexed(ii, *scripts.at(ii)->scriptData()->scriptValueForContext(ctxt).valueRef());
+ scriptsArray->putIndexed(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)));
if (!hasEngine())
initialize(parentCtxt->engine);
@@ -2535,13 +2534,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
if (!m_program) {
if (shared)
m_loaded = true;
- return QV4::PersistentValue();
+ return QV4::Encode::undefined();
}
- QV4::Scoped<QV4::QmlContextWrapper> qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
- qmlglobal->takeContextOwnership();
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, 0));
+ qmlContext->takeContextOwnership();
- m_program->qml.set(scope.engine, qmlglobal);
+ m_program->qmlContext.set(scope.engine, qmlContext);
m_program->run();
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
@@ -2549,13 +2548,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
ep->warning(error);
}
- rv.set(scope.engine, qmlglobal);
+ QV4::ScopedValue retval(scope, qmlContext->d()->qml);
if (shared) {
- m_value = rv;
+ m_value.set(scope.engine, retval);
m_loaded = true;
}
- return rv;
+ return retval->asReturnedValue();
}
void QQmlScriptData::clear()
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 5be478fa65..e7b4b8f95b 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -474,7 +474,7 @@ public:
QQmlTypeNameCache *importCache;
QList<QQmlScriptBlob *> scripts;
- QV4::PersistentValue scriptValueForContext(QQmlContextData *parentCtxt);
+ QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
protected:
virtual void clear(); // From QQmlCleanup
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 1d72b2da0d..d70a4019b2 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -48,12 +48,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
-Heap::QmlTypeWrapper::QmlTypeWrapper(ExecutionEngine *engine)
- : Heap::Object(engine)
- , mode(IncludeEnums)
- , type(Q_NULLPTR)
- , typeNamespace(Q_NULLPTR)
- , importNamespace(Q_NULLPTR)
+Heap::QmlTypeWrapper::QmlTypeWrapper()
+ : mode(IncludeEnums)
{
}
@@ -103,7 +99,7 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
Q_ASSERT(t);
Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine));
+ Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o; w->d()->type = t;
return w.asReturnedValue();
}
@@ -117,7 +113,7 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q
Q_ASSERT(importNamespace);
Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine));
+ Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
@@ -182,7 +178,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope
if (name->startsWithUpper()) {
bool ok = false;
- int value = type->enumValue(name, &ok);
+ int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
if (ok)
return QV4::Primitive::fromInt32(value).asReturnedValue();
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 14741a5bad..e67b457c59 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -66,7 +66,7 @@ struct QmlTypeWrapper : Object {
ExcludeEnums
};
- QmlTypeWrapper(QV4::ExecutionEngine *engine);
+ QmlTypeWrapper();
~QmlTypeWrapper();
TypeNameMode mode;
QPointer<QObject> object;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index b0ab85199d..8ddf91ef3c 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -55,7 +55,7 @@ namespace Heap {
struct QQmlValueTypeReference : QQmlValueTypeWrapper
{
- QQmlValueTypeReference(ExecutionEngine *engine);
+ QQmlValueTypeReference() {}
QPointer<QObject> object;
int property;
};
@@ -77,11 +77,6 @@ DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeReference);
using namespace QV4;
-Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine)
- : Heap::Object(engine)
-{
-}
-
Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
{
if (gadgetPtr) {
@@ -107,11 +102,6 @@ QVariant Heap::QQmlValueTypeWrapper::toVariant() const
}
-Heap::QQmlValueTypeReference::QQmlValueTypeReference(ExecutionEngine *engine)
- : Heap::QQmlValueTypeWrapper(engine)
-{
-}
-
bool QQmlValueTypeReference::readReferenceValue() const
{
if (!d()->object)
@@ -164,7 +154,7 @@ bool QQmlValueTypeReference::readReferenceValue() const
void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4)
{
- if (v4->valueTypeWrapperPrototype()->as<Object>())
+ if (v4->valueTypeWrapperPrototype()->d())
return;
Scope scope(v4);
@@ -178,10 +168,9 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
- ScopedObject proto(scope, engine->valueTypeWrapperPrototype());
- r->setPrototype(proto);
- r->d()->object = object; r->d()->property = property;
+ Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>());
+ r->d()->object = object;
+ r->d()->property = property;
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = 0;
@@ -193,9 +182,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
- ScopedObject proto(scope, engine->valueTypeWrapperPrototype());
- r->setPrototype(proto);
+ Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>());
r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = 0;
@@ -345,12 +332,9 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
if (hasProperty)
*hasProperty = true;
- if (result->isFunction()) {
+ if (result->isFunction())
// calling a Q_INVOKABLE function of a value type
- Scope scope(v4);
- ScopedContext c(scope, v4->rootContext());
- return QV4::QObjectMethod::create(c, r, result->coreIndex);
- }
+ return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex);
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
if (result->propType == metatype) { \
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 5f0edfb71d..156b4c85d8 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -61,7 +61,7 @@ namespace QV4 {
namespace Heap {
struct QQmlValueTypeWrapper : Object {
- QQmlValueTypeWrapper(ExecutionEngine *engine);
+ QQmlValueTypeWrapper() {}
~QQmlValueTypeWrapper();
QQmlRefPointer<QQmlPropertyCache> propertyCache;
mutable void *gadgetPtr;
@@ -76,6 +76,7 @@ struct QQmlValueTypeWrapper : Object {
struct Q_QML_EXPORT QQmlValueTypeWrapper : Object
{
V4_OBJECT2(QQmlValueTypeWrapper, Object)
+ V4_PROTOTYPE(valueTypeWrapperPrototype)
static void destroy(Heap::Base *b);
public:
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 427e751f5d..dcf95b0c69 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -271,8 +271,6 @@ public:
QList<QQmlVMEVariantQObjectPtr *> varObjectGuards;
QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const;
-
- friend class QV8GCCallback;
};
QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index de7741675b..8666c0db01 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -170,7 +170,7 @@ public:
namespace Heap {
struct NamedNodeMap : Object {
- NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list);
+ NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list);
~NamedNodeMap() {
if (d)
d->release();
@@ -180,7 +180,7 @@ struct NamedNodeMap : Object {
};
struct NodeList : Object {
- NodeList(ExecutionEngine *engine, NodeImpl *data);
+ NodeList(NodeImpl *data);
~NodeList() {
if (d)
d->release();
@@ -189,11 +189,11 @@ struct NodeList : Object {
};
struct NodePrototype : Object {
- NodePrototype(ExecutionEngine *engine);
+ NodePrototype();
};
struct Node : Object {
- Node(ExecutionEngine *engine, NodeImpl *data);
+ Node(NodeImpl *data);
~Node() {
if (d)
d->release();
@@ -217,9 +217,8 @@ public:
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
-Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
- : Heap::Object(engine)
- , list(list)
+Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list)
+ : list(list)
, d(data)
{
if (d)
@@ -243,9 +242,8 @@ public:
};
-Heap::NodeList::NodeList(ExecutionEngine *engine, NodeImpl *data)
- : Heap::Object(engine)
- , d(data)
+Heap::NodeList::NodeList(NodeImpl *data)
+ : d(data)
{
if (d)
d->addref();
@@ -285,10 +283,9 @@ public:
};
-Heap::NodePrototype::NodePrototype(ExecutionEngine *engine)
- : Heap::Object(engine)
+Heap::NodePrototype::NodePrototype()
{
- Scope scope(engine);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, 0);
@@ -323,9 +320,8 @@ private:
Node(const Node &o);
};
-Heap::Node::Node(ExecutionEngine *engine, NodeImpl *data)
- : Heap::Object(engine)
- , d(data)
+Heap::Node::Node(NodeImpl *data)
+ : d(data)
{
if (d)
d->addref();
@@ -584,7 +580,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
Scope scope(v4);
QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->nodePrototype.isUndefined()) {
- ScopedObject p(scope, v4->memoryManager->alloc<NodePrototype>(v4));
+ ScopedObject p(scope, v4->memoryManager->allocObject<NodePrototype>());
d->nodePrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
@@ -595,7 +591,7 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
{
Scope scope(v4);
- Scoped<Node> instance(scope, v4->memoryManager->alloc<Node>(v4, data));
+ Scoped<Node> instance(scope, v4->memoryManager->allocObject<Node>(data));
ScopedObject p(scope);
switch (data->type) {
@@ -863,7 +859,7 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
return Encode::null();
}
- ScopedObject instance(scope, v4->memoryManager->alloc<Node>(v4, document));
+ ScopedObject instance(scope, v4->memoryManager->allocObject<Node>(document));
ScopedObject p(scope);
instance->setPrototype((p = Document::prototype(v4)));
return instance.asReturnedValue();
@@ -916,7 +912,7 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert
ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list)
{
- return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue();
+ return (v4->memoryManager->allocObject<NamedNodeMap>(data, list))->asReturnedValue();
}
ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty)
@@ -950,7 +946,7 @@ ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
{
- return (v4->memoryManager->alloc<NodeList>(v4, data))->asReturnedValue();
+ return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue();
}
ReturnedValue Document::method_documentElement(CallContext *ctx)
@@ -1588,7 +1584,7 @@ namespace QV4 {
namespace Heap {
struct QQmlXMLHttpRequestWrapper : Object {
- QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request);
+ QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request);
~QQmlXMLHttpRequestWrapper() {
delete request;
}
@@ -1609,9 +1605,8 @@ struct QQmlXMLHttpRequestWrapper : public Object
V4_NEEDS_DESTROY
};
-Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
- : Heap::Object(engine)
- , request(request)
+Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request)
+ : request(request)
{
}
@@ -1632,7 +1627,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
return scope.engine->throwTypeError();
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager());
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(scope.engine, r));
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
return w.asReturnedValue();
@@ -2034,7 +2029,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
{
Scope scope(v4);
- Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4));
+ Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocObject<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
v4->globalObject->defineReadonlyProperty(s, ctor);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 239bc53f0a..5986fdbdfa 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -80,10 +80,9 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
-Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
- : Heap::Object(v4)
+Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
{
- Scope scope(v4);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
// Set all the enums from the "Qt" namespace
@@ -93,11 +92,11 @@ Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
- o->put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
+ o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
}
}
- o->put((str = v4->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
- o->put((str = v4->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
+ o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
+ o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
@@ -1262,7 +1261,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx)
if (!f)
V4THROW_TYPE("binding(): argument (binding expression) must be a function");
- return (ctx->d()->engine->memoryManager->alloc<QQmlBindingFunction>(f))->asReturnedValue();
+ return (ctx->d()->engine->memoryManager->allocObject<QQmlBindingFunction>(f))->asReturnedValue();
}
@@ -1315,10 +1314,9 @@ ReturnedValue QtObject::method_get_styleHints(CallContext *ctx)
}
-QV4::Heap::ConsoleObject::ConsoleObject(ExecutionEngine *v4)
- : Heap::Object(v4)
+QV4::Heap::ConsoleObject::ConsoleObject()
{
- QV4::Scope scope(v4);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->defineDefaultProperty(QStringLiteral("debug"), QV4::ConsoleObject::method_log);
@@ -1609,10 +1607,10 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
globalObject->defineDefaultProperty(QStringLiteral("print"), ConsoleObject::method_log);
globalObject->defineDefaultProperty(QStringLiteral("gc"), method_gc);
- ScopedObject console(scope, v4->memoryManager->alloc<QV4::ConsoleObject>(v4));
+ ScopedObject console(scope, v4->memoryManager->allocObject<QV4::ConsoleObject>());
globalObject->defineDefaultProperty(QStringLiteral("console"), console);
- ScopedObject qt(scope, v4->memoryManager->alloc<QV4::QtObject>(v4, qmlEngine));
+ ScopedObject qt(scope, v4->memoryManager->allocObject<QV4::QtObject>(qmlEngine));
globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
// string prototype extension
@@ -1737,10 +1735,10 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
int lastDot = path.lastIndexOf(QLatin1Char('.'));
int length = lastDot - (lastSlash + 1);
context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
- } else if (ctx->d()->parent) {
- ScopedContext parentCtx(scope, ctx->d()->parent);
+ } else {
+ ExecutionContext *parentCtx = scope.engine->parentContext(ctx);
// The first non-empty source URL in the call stack determines the translation context.
- while (parentCtx && context.isEmpty()) {
+ while (!!parentCtx && context.isEmpty()) {
if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) {
QString fileName = unit->fileName();
QUrl url(unit->fileName());
@@ -1753,7 +1751,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
}
context = QFileInfo(context).baseName();
}
- parentCtx = parentCtx->d()->parent;
+ parentCtx = scope.engine->parentContext(parentCtx);
}
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index bdd53fe601..bb05376fc0 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -58,13 +58,13 @@ namespace QV4 {
namespace Heap {
struct QtObject : Object {
- QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine);
+ QtObject(QQmlEngine *qmlEngine);
QObject *platform;
QObject *application;
};
struct ConsoleObject : Object {
- ConsoleObject(ExecutionEngine *engine);
+ ConsoleObject();
};
struct QQmlBindingFunction : FunctionObject {
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 6cb316ce9f..effc37a0eb 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -191,41 +191,47 @@ void QV8Engine::initializeGlobal()
m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
}
}
+}
- {
-#define FREEZE_SOURCE "(function freeze_recur(obj) { "\
- " if (Qt.isQtObject(obj)) return;"\
- " if (obj != Function.connect && obj != Function.disconnect && "\
- " obj instanceof Object) {"\
- " var properties = Object.getOwnPropertyNames(obj);"\
- " for (var prop in properties) { "\
- " if (prop == \"connect\" || prop == \"disconnect\") {"\
- " Object.freeze(obj[prop]); "\
- " continue;"\
- " }"\
- " freeze_recur(obj[prop]);"\
- " }"\
- " }"\
- " if (obj instanceof Object) {"\
- " Object.freeze(obj);"\
- " }"\
- "})"
-
- QV4::ScopedFunctionObject result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0));
- Q_ASSERT(!!result);
- m_freezeObject.set(scope.engine, result);
-#undef FREEZE_SOURCE
+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->prototype());
+ while (p) {
+ if (p->d() == v4->objectPrototype()->d()) {
+ instanceOfObject = true;
+ break;
+ }
+ p = p->prototype();
+ }
+ if (!instanceOfObject)
+ return;
+
+ QV4::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))
+ continue;
+ o = *object->propertyData(i);
+ if (o)
+ freeze_recursive(v4, o);
}
}
void QV8Engine::freezeObject(const QV4::Value &value)
{
QV4::Scope scope(m_v4Engine);
- QV4::ScopedFunctionObject f(scope, m_freezeObject.value());
- QV4::ScopedCallData callData(scope, 1);
- callData->args[0] = value;
- callData->thisObject = m_v4Engine->globalObject;
- f->call(callData);
+ QV4::ScopedObject o(scope, value);
+ freeze_recursive(m_v4Engine, o);
}
struct QV8EngineRegistrationData
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 08bbbb8548..552470c88c 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -120,8 +120,6 @@ class QQmlV4Function
public:
int length() const { return callData->argc; }
QV4::ReturnedValue operator[](int idx) { return (idx < callData->argc ? callData->args[idx].asReturnedValue() : QV4::Encode::undefined()); }
- QQmlContextData *context() { return e->qmlContextObject()->context.contextData(); }
- QV4::ReturnedValue qmlGlobal() { return e->qmlContextObject()->asReturnedValue(); }
void setReturnValue(QV4::ReturnedValue rv) { *retVal = rv; }
QV4::ExecutionEngine *v4engine() const { return e; }
private:
@@ -219,8 +217,6 @@ protected:
QV4::ExecutionEngine *m_v4Engine;
- QV4::PersistentValue m_freezeObject;
-
void *m_xmlHttpRequestData;
QVector<Deletable *> m_extensionData;
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index a154da8323..df429e5bc1 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -36,6 +36,7 @@
#include <private/qqmlnullablevalue_p.h>
#include <private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
+#include <private/qqmlmetatype_p.h>
#include <qqmlengine.h>
#include <qqmlcontext.h>
@@ -49,6 +50,29 @@
QT_BEGIN_NAMESPACE
+namespace {
+
+void validateProperty(QObject *target, const QString &propertyName, QObject *binding)
+{
+ if (!target)
+ return;
+
+ const QMetaObject *mo = target->metaObject();
+ const int index = mo->indexOfProperty(propertyName.toUtf8());
+ if (index == -1) {
+ qmlInfo(binding) << "Property '" << propertyName << "' does not exist on " << QQmlMetaType::prettyTypeName(target) << ".";
+ return;
+ }
+
+ const QMetaProperty mp = mo->property(index);
+ if (!mp.isWritable()) {
+ qmlInfo(binding) << "Property '" << propertyName << "' on " << QQmlMetaType::prettyTypeName(target) << " is read-only.";
+ return;
+ }
+}
+
+}
+
class QQmlBindPrivate : public QObjectPrivate
{
public:
@@ -186,8 +210,10 @@ void QQmlBind::setObject(QObject *obj)
d->when = true;
}
d->obj = obj;
- if (d->componentComplete)
+ if (d->componentComplete) {
+ validateProperty(d->obj, d->propName, this);
d->prop = QQmlProperty(d->obj, d->propName);
+ }
eval();
}
@@ -213,8 +239,10 @@ void QQmlBind::setProperty(const QString &p)
d->when = true;
}
d->propName = p;
- if (d->componentComplete)
+ if (d->componentComplete) {
+ validateProperty(d->obj, d->propName, this);
d->prop = QQmlProperty(d->obj, d->propName);
+ }
eval();
}
@@ -253,8 +281,10 @@ void QQmlBind::componentComplete()
{
Q_D(QQmlBind);
d->componentComplete = true;
- if (!d->prop.isValid())
+ if (!d->prop.isValid()) {
+ validateProperty(d->obj, d->propName, this);
d->prop = QQmlProperty(d->obj, d->propName);
+ }
eval();
}
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index bc70e68904..f2de911725 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -64,13 +64,13 @@ struct DelegateModelGroupFunction : FunctionObject {
};
struct QQmlDelegateModelGroupChange : Object {
- QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine);
+ QQmlDelegateModelGroupChange() {}
QQmlChangeSet::Change change;
};
struct QQmlDelegateModelGroupChangeArray : Object {
- QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes);
+ QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes);
QVector<QQmlChangeSet::Change> changes;
};
@@ -83,7 +83,7 @@ struct DelegateModelGroupFunction : QV4::FunctionObject
static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
{
- return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
+ return scope->engine()->memoryManager->allocObject<DelegateModelGroupFunction>(scope, flag, code);
}
static QV4::ReturnedValue call(const QV4::Managed *that, QV4::CallData *callData)
@@ -1717,7 +1717,7 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
s = v4->newString(QStringLiteral("isUnresolved"));
QV4::ScopedFunctionObject f(scope);
- QV4::ScopedContext global(scope, scope.engine->rootContext());
+ QV4::ExecutionContext *global = scope.engine->rootContext();
p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, 30, QQmlDelegateModelItem::get_member)));
p->setSetter(0);
proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -2488,7 +2488,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
QV8Engine *v8 = model->m_cacheMetaType->v8Engine;
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, cacheItem));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
o->setPrototype(p);
++cacheItem->scriptRef;
@@ -3233,7 +3233,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object
V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
- return e->memoryManager->alloc<QQmlDelegateModelGroupChange>(e);
+ return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>();
}
static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
@@ -3261,11 +3261,6 @@ struct QQmlDelegateModelGroupChange : QV4::Object
}
};
-QV4::Heap::QQmlDelegateModelGroupChange::QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
- : QV4::Heap::Object(engine)
-{
-}
-
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
struct QQmlDelegateModelGroupChangeArray : public QV4::Object
@@ -3275,7 +3270,7 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object
public:
static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
- return engine->memoryManager->alloc<QQmlDelegateModelGroupChangeArray>(engine, changes);
+ return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes);
}
quint32 count() const { return d()->changes.count(); }
@@ -3321,11 +3316,10 @@ public:
}
};
-QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
- : QV4::Heap::Object(engine)
- , changes(changes)
+QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes)
+ : changes(changes)
{
- QV4::Scope scope(engine);
+ QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(QV4::Heap::ArrayData::Custom);
}
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 5c28021c0e..3a19163cbd 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -154,7 +154,7 @@ protected:
namespace QV4 {
namespace Heap {
struct QQmlDelegateModelItemObject : Object {
- inline QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item);
+ inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item);
~QQmlDelegateModelItemObject();
QQmlDelegateModelItem *item;
};
@@ -168,9 +168,8 @@ struct QQmlDelegateModelItemObject : QV4::Object
V4_NEEDS_DESTROY
};
-QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
- : QV4::Heap::Object(engine)
- , item(item)
+QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QQmlDelegateModelItem *item)
+ : item(item)
{
}
diff --git a/src/qml/types/qqmlitemselectionmodel.qdoc b/src/qml/types/qqmlitemselectionmodel.qdoc
index 185ffb5fa4..441d219de8 100644
--- a/src/qml/types/qqmlitemselectionmodel.qdoc
+++ b/src/qml/types/qqmlitemselectionmodel.qdoc
@@ -103,7 +103,7 @@
*/
/*!
- \qmlmethod QItemSelection selection()
+ \qmlmethod QItemSelection ItemSelectionModel::selection()
*/
/*!
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 799f7a0b8a..a4c0f7043f 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -1875,6 +1875,30 @@ QVariant QQmlListModel::data(const QModelIndex &index, int role) const
return data(index.row(), role);
}
+bool QQmlListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int row = index.row();
+ if (row >= count() || row < 0)
+ return false;
+
+ if (m_dynamicRoles) {
+ const QByteArray property = m_roles.at(role).toUtf8();
+ if (m_modelObjects[row]->setValue(property, value)) {
+ emitItemsChanged(row, 1, QVector<int>() << role);
+ return true;
+ }
+ } else {
+ const ListLayout::Role &r = m_listModel->getExistingRole(role);
+ const int roleIndex = m_listModel->setOrCreateProperty(row, r.name, value);
+ if (roleIndex != -1) {
+ emitItemsChanged(row, 1, QVector<int>() << role);
+ return true;
+ }
+ }
+
+ return false;
+}
+
QVariant QQmlListModel::data(int index, int role) const
{
QVariant v;
@@ -2252,7 +2276,7 @@ QQmlV4Handle QQmlListModel::get(int index) const
result = QV4::QObjectWrapper::wrap(scope.engine, object);
} else {
QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- result = scope.engine->memoryManager->alloc<QV4::ModelObject>(scope.engine, object, const_cast<QQmlListModel *>(this), index);
+ result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this), index);
}
}
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index b5a5ef3265..21de392234 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -71,6 +71,7 @@ public:
QModelIndex index(int row, int column, const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
QHash<int,QByteArray> roleNames() const;
QVariant data(int index, int role) const;
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index bd0f028e7a..d7e0defaec 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -155,8 +155,8 @@ namespace QV4 {
namespace Heap {
struct ModelObject : public QObjectWrapper {
- ModelObject(QV4::ExecutionEngine *engine, QObject *object, QQmlListModel *model, int elementIndex)
- : QObjectWrapper(engine, object)
+ ModelObject(QObject *object, QQmlListModel *model, int elementIndex)
+ : QObjectWrapper(object)
, m_model(model)
, m_elementIndex(elementIndex)
{}
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 0aa5dc4ef6..03915ab414 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -165,7 +165,7 @@ public:
QUrl source;
bool initialized;
QQuickWorkerScript *owner;
- QV4::PersistentValue object;
+ QV4::PersistentValue qmlContext;
};
QHash<int, WorkerScript *> workers;
@@ -221,7 +221,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
"})"
QV4::Scope scope(m_v4Engine);
- QV4::ScopedContext globalContext(scope, scope.engine->rootContext());
+ QV4::ExecutionContext *globalContext = scope.engine->rootContext();
onmessage.set(scope.engine, QV4::Script(globalContext, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
Q_ASSERT(!scope.engine->hasException);
QV4::Script createsendscript(globalContext, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
@@ -291,7 +291,6 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Call
return QV4::Encode::undefined();
}
-// Requires handle scope and context scope
QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script)
{
if (!script->initialized) {
@@ -300,9 +299,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
QV4::Scope scope(v4);
- script->object.set(v4, QV4::QmlContextWrapper::urlScope(v4, script->source));
-
- QV4::Scoped<QV4::QmlContextWrapper> w(scope, script->object.value());
+ QV4::Scoped<QV4::QmlContextWrapper> w(scope, QV4::QmlContextWrapper::urlScope(v4, script->source));
Q_ASSERT(!!w);
w->setReadOnly(false);
@@ -312,9 +309,11 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))), api);
w->setReadOnly(true);
+
+ script->qmlContext.set(v4, v4->rootContext()->newQmlContext(w));
}
- return script->object.value();
+ return script->qmlContext.value();
}
bool QQuickWorkerScriptEnginePrivate::event(QEvent *event)
@@ -354,10 +353,12 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
QV4::ScopedFunctionObject f(scope, workerEngine->onmessage.value());
QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, script->qmlContext.value());
+ Q_ASSERT(!!qmlContext);
QV4::ScopedCallData callData(scope, 2);
callData->thisObject = workerEngine->global();
- callData->args[0] = script->object.value();
+ callData->args[0] = qmlContext->d()->qml; // ###
callData->args[1] = value;
f->call(callData);
if (scope.hasException()) {
@@ -382,13 +383,12 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
return;
script->source = url;
- QV4::ScopedObject activation(scope, getWorker(script));
- if (!activation)
- return;
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, getWorker(script));
+ Q_ASSERT(!!qmlContext);
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- program.reset(new QV4::Script(v4, activation, jsUnit));
+ program.reset(new QV4::Script(v4, qmlContext, jsUnit));
} else {
QFile f(fileName);
if (!f.open(QIODevice::ReadOnly)) {
@@ -400,7 +400,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
QString sourceCode = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(sourceCode);
- program.reset(new QV4::Script(v4, activation, sourceCode, url.toString()));
+ program.reset(new QV4::Script(v4, qmlContext, sourceCode, url.toString()));
program->parse();
}
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index f83798488c..29398ff98c 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -221,9 +221,9 @@ public:
const QByteArray &propertyName = it.key();
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::ScopedContext global(scope, v4->rootContext());
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
+ QV4::ExecutionContext *global = v4->rootContext();
+ QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
+ QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocObject<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
p->setGetter(g);
p->setSetter(s);
proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
@@ -428,7 +428,7 @@ public:
}
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, proto->engine()->memoryManager->alloc<QQmlDelegateModelItemObject>(proto->engine(), this));
+ QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
o->setPrototype(proto);
++scriptRef;
return o.asReturnedValue();
@@ -606,7 +606,7 @@ public:
{
QQmlAdaptorModelEngineData *data = engineData(v4);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, this));
+ QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(this));
QV4::ScopedObject p(scope, data->listItemProto.value());
o->setPrototype(p);
++scriptRef;
diff --git a/src/qml/util/qqmllistcompositor_p.h b/src/qml/util/qqmllistcompositor_p.h
index 8e10cb1546..2ddbc5d5a1 100644
--- a/src/qml/util/qqmllistcompositor_p.h
+++ b/src/qml/util/qqmllistcompositor_p.h
@@ -166,7 +166,7 @@ public:
struct Change
{
inline Change() {}
- inline Change(iterator it, int count, uint flags, int moveId = -1);
+ inline Change(const iterator &it, int count, uint flags, int moveId = -1);
int count;
uint flags;
int moveId;
@@ -188,14 +188,14 @@ public:
struct Insert : public Change
{
Insert() {}
- Insert(iterator it, int count, uint flags, int moveId = -1)
+ Insert(const iterator &it, int count, uint flags, int moveId = -1)
: Change(it, count, flags, moveId) {}
};
struct Remove : public Change
{
Remove() {}
- Remove(iterator it, int count, uint flags, int moveId = -1)
+ Remove(const iterator &it, int count, uint flags, int moveId = -1)
: Change(it, count, flags, moveId) {}
};
@@ -224,14 +224,14 @@ public:
void setFlags(iterator from, int count, Group group, uint flags, QVector<Insert> *inserts = 0);
void setFlags(Group fromGroup, int from, int count, uint flags, QVector<Insert> *inserts = 0) {
setFlags(fromGroup, from, count, fromGroup, flags, inserts); }
- void setFlags(iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
+ void setFlags(const iterator from, int count, uint flags, QVector<Insert> *inserts = 0) {
setFlags(from, count, from.group, flags, inserts); }
void clearFlags(Group fromGroup, int from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
void clearFlags(iterator from, int count, Group group, uint flags, QVector<Remove> *removals = 0);
void clearFlags(Group fromGroup, int from, int count, uint flags, QVector<Remove> *removals = 0) {
clearFlags(fromGroup, from, count, fromGroup, flags, removals); }
- void clearFlags(iterator from, int count, uint flags, QVector<Remove> *removals = 0) {
+ void clearFlags(const iterator &from, int count, uint flags, QVector<Remove> *removals = 0) {
clearFlags(from, count, from.group, flags, removals); }
bool verifyMoveTo(Group fromGroup, int from, Group toGroup, int to, int count, Group group) const;
@@ -347,7 +347,7 @@ inline QQmlListCompositor::insert_iterator::insert_iterator(
Range *range, int offset, Group group, int groupCount)
: iterator(range, offset, group, groupCount) {}
-inline QQmlListCompositor::Change::Change(iterator it, int count, uint flags, int moveId)
+inline QQmlListCompositor::Change::Change(const iterator &it, int count, uint flags, int moveId)
: count(count), flags(flags), moveId(moveId)
{
for (int i = 0; i < MaximumGroupCount; ++i)
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 2e95ab7cb5..28f3c8f215 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -172,8 +172,7 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu
modify or clear its associated value.
\note When deriving a class from QQmlPropertyMap, use the
- \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)}
- {protected two-argument constructor}
+ \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)} {protected two-argument constructor}
which ensures that the class is correctly registered with the Qt \l {Meta-Object System}.
*/