aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/jsruntime.pri6
-rw-r--r--src/qml/jsruntime/qv4alloca_p.h11
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp62
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h24
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp27
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h20
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp139
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h64
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4context.cpp403
-rw-r--r--src/qml/jsruntime/qv4context_p.h83
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp44
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h20
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp175
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h41
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp645
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h140
-rw-r--r--src/qml/jsruntime/qv4engine.cpp826
-rw-r--r--src/qml/jsruntime/qv4engine_p.h382
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp214
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h124
-rw-r--r--src/qml/jsruntime/qv4executableallocator_p.h11
-rw-r--r--src/qml/jsruntime/qv4function.cpp35
-rw-r--r--src/qml/jsruntime/qv4function_p.h18
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp261
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h87
-rw-r--r--src/qml/jsruntime/qv4global_p.h18
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp87
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h11
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp16
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h17
-rw-r--r--src/qml/jsruntime/qv4include.cpp35
-rw-r--r--src/qml/jsruntime/qv4include_p.h8
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp87
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h14
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp162
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h65
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp161
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h31
-rw-r--r--src/qml/jsruntime/qv4managed.cpp30
-rw-r--r--src/qml/jsruntime/qv4managed_p.h134
-rw-r--r--src/qml/jsruntime/qv4math_p.h11
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h13
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp31
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h14
-rw-r--r--src/qml/jsruntime/qv4mm.cpp651
-rw-r--r--src/qml/jsruntime/qv4mm_p.h198
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h15
-rw-r--r--src/qml/jsruntime/qv4object.cpp376
-rw-r--r--src/qml/jsruntime/qv4object_p.h199
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp47
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h24
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp78
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h15
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp95
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h39
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp47
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h22
-rw-r--r--src/qml/jsruntime/qv4property_p.h24
-rw-r--r--src/qml/jsruntime/qv4qmlextensions.cpp43
-rw-r--r--src/qml/jsruntime/qv4qmlextensions_p.h58
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp320
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h45
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp25
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h14
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp117
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h50
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp328
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h47
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h205
-rw-r--r--src/qml/jsruntime/qv4script.cpp164
-rw-r--r--src/qml/jsruntime/qv4script_p.h61
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp51
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h5
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp22
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h2
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp11
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h23
-rw-r--r--src/qml/jsruntime/qv4string.cpp4
-rw-r--r--src/qml/jsruntime/qv4string_p.h25
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp100
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h39
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp57
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h30
-rw-r--r--src/qml/jsruntime/qv4util_p.h11
-rw-r--r--src/qml/jsruntime/qv4value.cpp78
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h293
-rw-r--r--src/qml/jsruntime/qv4value_p.h472
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp83
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h11
98 files changed, 4350 insertions, 5241 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index ef44ca6f4d..5ffdebe328 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -10,7 +10,6 @@ SOURCES += \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
$$PWD/qv4identifiertable.cpp \
- $$PWD/qv4mm.cpp \
$$PWD/qv4managed.cpp \
$$PWD/qv4internalclass.cpp \
$$PWD/qv4sparsearray.cpp \
@@ -40,7 +39,6 @@ SOURCES += \
$$PWD/qv4sequenceobject.cpp \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
- $$PWD/qv4qmlextensions.cpp \
$$PWD/qv4vme_moth.cpp \
$$PWD/qv4profiling.cpp \
$$PWD/qv4arraybuffer.cpp \
@@ -57,7 +55,6 @@ HEADERS += \
$$PWD/qv4lookup_p.h \
$$PWD/qv4identifier_p.h \
$$PWD/qv4identifiertable_p.h \
- $$PWD/qv4mm_p.h \
$$PWD/qv4managed_p.h \
$$PWD/qv4internalclass_p.h \
$$PWD/qv4sparsearray_p.h \
@@ -90,7 +87,6 @@ HEADERS += \
$$PWD/qv4sequenceobject_p.h \
$$PWD/qv4include_p.h \
$$PWD/qv4qobjectwrapper_p.h \
- $$PWD/qv4qmlextensions_p.h \
$$PWD/qv4vme_moth_p.h \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
@@ -102,7 +98,7 @@ HEADERS += \
HEADERS += \
$$PWD/qv4runtime_p.h \
- $$PWD/qv4value_inl_p.h \
+ $$PWD/qv4value_p.h \
$$PWD/qv4string_p.h \
$$PWD/qv4value_p.h
diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h
index a4537868e2..df40a018ba 100644
--- a/src/qml/jsruntime/qv4alloca_p.h
+++ b/src/qml/jsruntime/qv4alloca_p.h
@@ -34,6 +34,17 @@
#ifndef QV4_ALLOCA_H
#define QV4_ALLOCA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qglobal.h>
#if defined(Q_OS_WIN)
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 92c77570af..698b4c325c 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -33,18 +33,17 @@
#include <qv4argumentsobject_p.h>
#include <qv4alloca_p.h>
#include <qv4scopedvalue_p.h>
+#include "qv4string_p.h"
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.asObject())
- , context(context->d())
+ : context(context->d())
, fullyCreated(false)
{
- Q_ASSERT(vtable == QV4::ArgumentsObject::staticVTable());
+ Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
ExecutionEngine *v4 = context->d()->engine;
Scope scope(v4);
@@ -53,22 +52,22 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
args->setArrayType(Heap::ArrayData::Complex);
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;
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
+ Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller()));
+ *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();
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
+ *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);
+ Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
+ *args->propertyData(LengthPropertyIndex) = Primitive::fromInt32(context->d()->callData->argc);
}
void ArgumentsObject::fullyCreate()
@@ -76,17 +75,16 @@ void ArgumentsObject::fullyCreate()
if (fullyCreated())
return;
- uint numAccessors = qMin((int)context()->function->formalParameterCount(), context()->callData->argc);
uint argCount = context()->callData->argc;
+ uint numAccessors = qMin(context()->function->formalParameterCount(), argCount);
ArrayData::realloc(this, Heap::ArrayData::Sparse, argCount, true);
context()->engine->requireArgumentsAccessors(numAccessors);
Scope scope(engine());
Scoped<MemberData> md(scope, d()->mappedArguments);
- if (!md || md->size() < numAccessors)
- d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
- for (uint i = 0; i < (uint)numAccessors; ++i) {
- mappedArguments()->data[i] = context()->callData->args[i];
+ d()->mappedArguments = md->allocate(engine(), numAccessors);
+ for (uint i = 0; i < numAccessors; ++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);
@@ -116,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());
@@ -139,14 +137,14 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
}
}
- if (engine->currentContext()->strictMode && !result)
+ if (engine->current->strictMode && !result)
return engine->throwTypeError();
return result;
}
-ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
if (args->fullyCreated())
return Object::getIndexed(m, index, hasProperty);
@@ -199,11 +197,11 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
-ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
+ReturnedValue ArgumentsGetterFunction::call(const Managed *getter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsGetterFunction *>(getter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsGetterFunction *>(getter)->engine();
Scope scope(v4);
- Scoped<ArgumentsGetterFunction> g(scope, static_cast<ArgumentsGetterFunction *>(getter));
+ Scoped<ArgumentsGetterFunction> g(scope, static_cast<const ArgumentsGetterFunction *>(getter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
@@ -214,11 +212,11 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
-ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
+ReturnedValue ArgumentsSetterFunction::call(const Managed *setter, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArgumentsSetterFunction *>(setter)->engine();
+ ExecutionEngine *v4 = static_cast<const ArgumentsSetterFunction *>(setter)->engine();
Scope scope(v4);
- Scoped<ArgumentsSetterFunction> s(scope, static_cast<ArgumentsSetterFunction *>(setter));
+ Scoped<ArgumentsSetterFunction> s(scope, static_cast<const ArgumentsSetterFunction *>(setter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
return v4->throwTypeError();
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 43cd6d1dee..7a9c4b1d51 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARGUMENTSOBJECTS_H
#define QV4ARGUMENTSOBJECTS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
@@ -59,9 +70,9 @@ struct ArgumentsObject : Object {
CallerPropertyIndex = 3
};
ArgumentsObject(QV4::CallContext *context);
- CallContext *context;
+ Pointer<CallContext> context;
bool fullyCreated;
- MemberData *mappedArguments;
+ Pointer<MemberData> mappedArguments;
};
}
@@ -71,7 +82,7 @@ struct ArgumentsGetterFunction: FunctionObject
V4_OBJECT2(ArgumentsGetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *d);
};
inline
@@ -86,7 +97,7 @@ struct ArgumentsSetterFunction: FunctionObject
V4_OBJECT2(ArgumentsSetterFunction, FunctionObject)
uint index() const { return d()->index; }
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
inline
@@ -103,15 +114,14 @@ 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 &&
+ return m->d()->vtable()->type == Type_ArgumentsObject &&
!static_cast<ArgumentsObject *>(m)->context()->strictMode;
}
bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index dc65b5d21a..0a3aa414de 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -33,6 +33,7 @@
#include "qv4arraybuffer_p.h"
#include "qv4typedarray_p.h"
#include "qv4dataview_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -44,9 +45,9 @@ Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue l(scope, callData->argument(0));
@@ -57,14 +58,14 @@ ReturnedValue ArrayBufferCtor::construct(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();
}
-ReturnedValue ArrayBufferCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayBufferCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -82,22 +83,20 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
}
-Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length)
- : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject())
+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.asObject())
- , data(const_cast<QByteArray&>(array).data_ptr())
+Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array)
+ : data(const_cast<QByteArray&>(array).data_ptr())
{
data->ref.ref();
}
@@ -138,10 +137,10 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
}
@@ -172,7 +171,7 @@ ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx)
double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index fe3150618d..56f45b5a72 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARRAYBUFFER_H
#define QV4ARRAYBUFFER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
@@ -47,8 +58,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;
@@ -61,8 +72,8 @@ struct ArrayBufferCtor: FunctionObject
{
V4_OBJECT2(ArrayBufferCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static ReturnedValue method_isView(CallContext *ctx);
@@ -72,6 +83,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 afcfa00905..ec0185de64 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -33,13 +33,14 @@
#include "qv4arraydata_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4runtime_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
-const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
+const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
QV4::ArrayData::IsExecutionContext,
QV4::ArrayData::IsString,
@@ -90,6 +91,13 @@ const ArrayVTable SparseArrayData::static_vtbl =
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
+static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
+{
+ Value v = Value::fromReturnedValue(*target);
+ v.setValue(value);
+ *target = v.asReturnedValue();
+}
+
void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAttributes)
{
Scope scope(o->engine());
@@ -165,7 +173,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
Heap::SparseArrayData *sparse = static_cast<Heap::SparseArrayData *>(newData->d());
- uint *lastFree;
+ ReturnedValue *lastFree;
if (d && d->type() == Heap::ArrayData::Sparse) {
Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
sparse->sparse = old->sparse;
@@ -180,20 +188,20 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
}
}
if (toCopy < sparse->alloc) {
for (uint i = toCopy; i < sparse->alloc; ++i) {
- *lastFree = i;
- sparse->arrayData[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData[i].uint_32;
+ storeValue(lastFree, i);
+ sparse->arrayData[i].setTag(Value::Empty_Type);
+ lastFree = &sparse->arrayData[i].rawValueRef();
}
- *lastFree = UINT_MAX;
+ storeValue(lastFree, UINT_MAX);
}
// ### Could explicitly free the old data
}
@@ -230,7 +238,7 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
bool SimpleArrayData::put(Object *o, uint index, const Value &value)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
// ### honour attributes
dd->data(index) = value;
@@ -244,7 +252,7 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value)
bool SimpleArrayData::del(Object *o, uint index)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index >= dd->len)
return true;
@@ -266,12 +274,12 @@ void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes att
void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (dd->len + n > dd->alloc) {
realloc(o, Heap::ArrayData::Simple, dd->len + n, false);
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
dd->offset = (dd->offset - n) % dd->alloc;
dd->len += n;
@@ -281,7 +289,7 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Q_ASSERT(!dd->attrs);
if (!dd->len)
return Encode::undefined();
@@ -294,7 +302,7 @@ ReturnedValue SimpleArrayData::pop_front(Object *o)
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (dd->len < newLen)
return newLen;
@@ -318,10 +326,10 @@ uint SimpleArrayData::length(const Heap::ArrayData *d)
bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n)
{
- Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index + n > dd->alloc) {
reallocate(o, index + n + 1, false);
- dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
for (uint i = dd->len; i < index; ++i)
dd->data(i) = Primitive::emptyValue();
@@ -337,13 +345,10 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->arrayData + idx;
if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
- v[1].tag = Value::Empty_Type;
- v[1].uint_32 = d->freeList;
- v[0].tag = Value::Empty_Type;
- v[0].uint_32 = idx + 1;
+ v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
+ v[0].setTagValue(Value::Empty_Type, idx + 1);
} else {
- v->tag = Value::Empty_Type;
- v->uint_32 = d->freeList;
+ v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value());
}
d->freeList = idx;
if (d->attrs)
@@ -369,35 +374,37 @@ Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttr
uint SparseArrayData::allocate(Object *o, bool doubleSlot)
{
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (doubleSlot) {
- uint *last = &dd->freeList;
+ ReturnedValue *last = &dd->freeList;
while (1) {
- if (*last == UINT_MAX) {
+ if (Value::fromReturnedValue(*last).value() == UINT_MAX) {
reallocate(o, dd->alloc + 2, true);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
last = &dd->freeList;
- Q_ASSERT(*last != UINT_MAX);
+ Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
}
- Q_ASSERT(dd->arrayData[*last].uint_32 != *last);
- if (dd->arrayData[*last].uint_32 == (*last + 1)) {
+ Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value());
+ if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) {
// found two slots in a row
- uint idx = *last;
- *last = dd->arrayData[*last + 1].uint_32;
+ uint idx = Value::fromReturnedValue(*last).uint_32();
+ Value lastV = Value::fromReturnedValue(*last);
+ lastV.setValue(dd->arrayData[lastV.value() + 1].value());
+ *last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->arrayData[*last].uint_32;
+ last = &dd->arrayData[Value::fromReturnedValue(*last).value()].rawValueRef();
}
} else {
- if (dd->freeList == UINT_MAX) {
+ if (Value::fromReturnedValue(dd->freeList).value() == UINT_MAX) {
reallocate(o, dd->alloc + 1, false);
- dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- uint idx = dd->freeList;
+ uint idx = Value::fromReturnedValue(dd->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->arrayData[idx].uint_32;
+ dd->freeList = dd->arrayData[idx].uint_32();
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -418,12 +425,12 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
if (value.isEmpty())
return true;
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
Q_ASSERT(n->value == UINT_MAX || !s->attrs || !s->attrs[n->value].isAccessor());
if (n->value == UINT_MAX)
n->value = allocate(o);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
s->arrayData[n->value] = value;
if (s->attrs)
s->attrs[n->value] = Attr_Data;
@@ -432,7 +439,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value)
bool SparseArrayData::del(Object *o, uint index)
{
- Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *dd = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = dd->sparse->findNode(index);
if (!n)
@@ -452,13 +459,10 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->arrayData[pidx + 1].tag = Value::Empty_Type;
- dd->arrayData[pidx + 1].uint_32 = dd->freeList;
- dd->arrayData[pidx].tag = Value::Undefined_Type;
- dd->arrayData[pidx].uint_32 = pidx + 1;
+ dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
+ dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1);
} else {
- dd->arrayData[pidx].tag = Value::Empty_Type;
- dd->arrayData[pidx].uint_32 = dd->freeList;
+ dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value());
}
dd->freeList = pidx;
@@ -468,28 +472,28 @@ bool SparseArrayData::del(Object *o, uint index)
void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = d->sparse->insert(index);
if (n->value == UINT_MAX) {
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
// need to convert the slot
free(o->arrayData(), n->value);
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
}
d->attrs[n->value] = attrs;
}
void SparseArrayData::push_front(Object *o, const Value *values, uint n)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
for (int i = n - 1; i >= 0; --i) {
uint idx = allocate(o);
- d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SparseArrayData>();
d->arrayData[idx] = values[i];
d->sparse->push_front(idx);
}
@@ -497,7 +501,7 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n)
ReturnedValue SparseArrayData::pop_front(Object *o)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
Q_ASSERT(!d->attrs);
uint idx = d->sparse->pop_front();
ReturnedValue v;
@@ -512,7 +516,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint SparseArrayData::truncate(Object *o, uint newLen)
{
- Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *begin = d->sparse->lowerBound(newLen);
if (begin != d->sparse->end()) {
SparseArrayNode *it = d->sparse->end()->previousNode();
@@ -580,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 {
@@ -603,14 +607,14 @@ 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 = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (index < 0x1000 || index < d->len + (d->len >> 2)) {
if (index >= d->alloc) {
o->arrayReserve(index + 1);
- d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ d = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
if (index >= d->len) {
// mark possible hole in the array
@@ -618,17 +622,20 @@ 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;
}
}
o->initSparseArray();
- Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>();
SparseArrayNode *n = s->sparse->insert(index);
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
- s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
- return reinterpret_cast<Property *>(s->arrayData + n->value);
+ s = o->d()->arrayData.cast<Heap::SparseArrayData>();
+ s->arrayData[n->value] = *v;
+ if (isAccessor)
+ s->arrayData[n->value + Object::SetterOffset] = v[Object::SetterOffset];
}
@@ -737,7 +744,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
if (!arrayData || !arrayData->length())
return;
- if (!(comparefn.isUndefined() || comparefn.asObject())) {
+ if (!(comparefn.isUndefined() || comparefn.as<Object>())) {
engine->throwTypeError();
return;
}
@@ -755,7 +762,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
thisObject->setArrayData(0);
ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
SparseArrayNode *n = sparse->sparse()->begin();
uint i = 0;
@@ -765,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();
@@ -795,7 +802,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
}
} else {
- Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > d->len)
len = d->len;
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 915e862bbb..48d2b9dbbf 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARRAYDATA_H
#define QV4ARRAYDATA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4managed_p.h"
#include "qv4property_p.h"
@@ -47,17 +58,17 @@ namespace QV4 {
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
static const QV4::ArrayVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- const Data *d() const { return static_cast<const Data *>(m); } \
- Data *d() { return static_cast<Data *>(m); }
+ const Data *d() const { return static_cast<const Data *>(m()); } \
+ Data *d() { return static_cast<Data *>(m()); }
struct ArrayData;
struct ArrayVTable
{
- ManagedVTable managedVTable;
+ VTable vTable;
uint type;
Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
@@ -86,7 +97,7 @@ struct ArrayData : public Base {
PropertyAttributes *attrs;
union {
uint len;
- uint freeList;
+ ReturnedValue freeList;
};
union {
uint offset;
@@ -96,12 +107,15 @@ struct ArrayData : public Base {
bool isSparse() const { return type == Sparse; }
- const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable); }
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
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 +219,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
@@ -239,8 +253,8 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
V4_ARRAYDATA(SparseArrayData)
V4_NEEDS_DESTROY
- uint &freeList() { return d()->freeList; }
- uint freeList() const { return d()->freeList; }
+ ReturnedValue &freeList() { return d()->freeList; }
+ ReturnedValue freeList() const { return d()->freeList; }
SparseArray *sparse() const { return d()->sparse; }
void setSparse(SparseArray *s) { d()->sparse = s; }
@@ -270,6 +284,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 +317,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/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 231eb93dd5..25d3d9329b 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -37,6 +37,7 @@
#include "qv4scopedvalue_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -47,9 +48,9 @@ Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<ArrayCtor *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const ArrayCtor *>(m)->engine();
Scope scope(v4);
ScopedArrayObject a(scope, v4->newArrayObject());
uint len;
@@ -72,7 +73,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
return a.asReturnedValue();
}
-ReturnedValue ArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -81,11 +82,11 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isArray"), method_isArray, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
defineDefaultProperty(QStringLiteral("join"), method_join, 1);
@@ -110,7 +111,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
{
- bool isArray = ctx->argc() && ctx->args()[0].asArrayObject();
+ bool isArray = ctx->argc() && ctx->args()[0].as<ArrayObject>();
return Encode(isArray);
}
@@ -185,7 +186,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
r4 = arg->toQString();
ScopedObject self(scope, ctx->thisObject());
- ScopedValue length(scope, self->get(ctx->d()->engine->id_length));
+ ScopedValue length(scope, self->get(ctx->d()->engine->id_length()));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
@@ -194,7 +195,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
QString R;
// ### FIXME
- if (ArrayObject *a = self->asArrayObject()) {
+ if (ArrayObject *a = self->as<ArrayObject>()) {
ScopedValue e(scope);
for (uint i = 0; i < a->getLength(); ++i) {
if (i)
@@ -242,7 +243,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -256,7 +257,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLength(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -282,7 +283,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
}
double newLen = l + ctx->argc();
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
return ctx->engine()->throwRangeError(str);
@@ -303,7 +304,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len)));
return Encode(len);
}
@@ -354,7 +355,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -388,7 +389,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result->asReturnedValue();
}
@@ -523,7 +524,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
}
ctx->d()->strictMode = true;
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
return newArray.asReturnedValue();
}
@@ -561,7 +562,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
else
- instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen)));
return Encode(newLen);
}
@@ -619,7 +620,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
return Encode(-1);
} else {
Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(instance->d()->arrayData);
+ Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>();
if (len > sa->len)
len = sa->len;
uint idx = fromIndex;
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 4e67eb2e31..afd8080fa3 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ARRAYOBJECT_H
#define QV4ARRAYOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct ArrayCtor: FunctionObject
{
V4_OBJECT2(ArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ArrayPrototype: ArrayObject
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 9c293e783b..53f8abf3f2 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4booleanobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -43,14 +44,14 @@ Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
+ReturnedValue BooleanCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<BooleanCtor *>(m)->engine());
+ Scope scope(static_cast<const BooleanCtor *>(m)->engine());
bool n = callData->argc ? callData->args[0].toBoolean() : false;
return Encode(scope.engine->newBooleanObject(n));
}
-ReturnedValue BooleanCtor::call(Managed *, CallData *callData)
+ReturnedValue BooleanCtor::call(const Managed *, CallData *callData)
{
bool value = callData->argc ? callData->args[0].toBoolean() : 0;
return Encode(value);
@@ -60,11 +61,11 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
}
ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
@@ -73,7 +74,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
if (ctx->thisObject().isBoolean()) {
result = ctx->thisObject().booleanValue();
} else {
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
result = thisObject->value();
@@ -87,7 +88,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
if (ctx->thisObject().isBoolean())
return ctx->thisObject().asReturnedValue();
- BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+ const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
if (!thisObject)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 903261bdce..203c8ba4ea 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4BOOLEANOBJECT_H
#define QV4BOOLEANOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct BooleanCtor: FunctionObject
{
V4_OBJECT2(BooleanCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct BooleanPrototype: BooleanObject
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 9330f10780..007bf92639 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -36,10 +36,12 @@
#include <qv4context_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include "qv4function_p.h"
#include "qv4errorobject_p.h"
+#include "qv4string_p.h"
+#include "private/qqmlcontextwrapper_p.h"
using namespace QV4;
@@ -48,8 +50,9 @@ DEFINE_MANAGED_VTABLE(CallContext);
DEFINE_MANAGED_VTABLE(WithContext);
DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
+DEFINE_MANAGED_VTABLE(QmlContext);
-Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
+Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *function, CallData *callData)
{
Q_ASSERT(function->function());
@@ -80,39 +83,64 @@ Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, Ca
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::CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
+Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
{
- Scope scope(this);
- Scoped<CallContext> c(scope, d()->engine->memoryManager->allocManaged<CallContext>(requiredMemoryForExecutionContect(f, 0)));
- new (c->d()) Heap::CallContext(d()->engine, qml, f);
- return c->d();
+ 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)
{
Scope scope(this);
// find the right context to create the binding on
- ScopedObject activation(scope, d()->engine->globalObject());
+ ScopedObject activation(scope);
ScopedContext ctx(scope, this);
while (ctx) {
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (!c->activation)
- c->activation = scope.engine->newObject();
- activation = c->activation;
+ if (!activation) {
+ if (!c->activation)
+ c->activation = scope.engine->newObject();
+ activation = c->activation;
+ }
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ // this is ugly, as it overrides the inner callcontext, but has to stay as long
+ // as bindings still get their own callcontext
+ Heap::QmlContext *qml = static_cast<Heap::QmlContext *>(ctx->d());
+ activation = qml->qml;
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ if (!activation)
+ activation = scope.engine->globalObject;
+ break;
+ }
+ default:
break;
}
ctx = ctx->d()->outer;
@@ -130,57 +158,46 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
: Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext)
{
- global = eng->globalObject()->d();
+ 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;
this->exceptionValue = exceptionValue;
}
-Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function)
- : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_QmlContext)
+Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml)
+ : Heap::ExecutionContext(outerContext->engine(), Heap::ExecutionContext::Type_QmlContext)
{
- this->function = function->d();
- callData = reinterpret_cast<CallData *>(this + 1);
- callData->tag = QV4::Value::_Integer_Type;
- callData->argc = 0;
- callData->thisObject = Primitive::undefinedValue();
-
+ outer = outerContext->d();
strictMode = false;
- outer = function->scope();
+ callData = outer->callData;
+ lookups = outer->lookups;
+ compilationUnit = outer->compilationUnit;
- activation = qml->d();
-
- if (function->function()) {
- compilationUnit = function->function()->compilationUnit;
- lookups = compilationUnit->runtimeLookups;
- }
-
- locals = (Value *)(this + 1);
- if (function->varCount())
- std::fill(locals, locals + function->varCount(), Primitive::undefinedValue());
+ this->qml = qml->d();
}
+
Identifier * const *CallContext::formals() const
{
return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() : 0;
@@ -209,16 +226,28 @@ bool ExecutionContext::deleteProperty(String *name)
bool hasWith = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return false;
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
hasWith = true;
ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (withObject->hasProperty(name))
return withObject->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return false;
- } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ if (global->hasProperty(name))
+ return global->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->needsActivation() || hasWith) {
@@ -227,13 +256,14 @@ bool ExecutionContext::deleteProperty(String *name)
// ### throw in strict mode?
return false;
}
- ScopedObject activation(scope, c->activation);
- if (activation && activation->hasProperty(name))
- return activation->deleteProperty(name);
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
- if (global->hasProperty(name))
- return global->deleteProperty(name);
+ ScopedObject qml(scope, c->activation);
+ if (qml && qml->hasProperty(name))
+ return qml->deleteProperty(name);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext:
+ // can't delete properties on qml objects
+ break;
}
}
@@ -254,7 +284,27 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (ctx->outer)
ctx->outer->mark(engine);
- if (ctx->type >= Heap::ExecutionContext::Type_CallContext) {
+ switch (ctx->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
+ c->exceptionVarName->mark(engine);
+ c->exceptionValue.mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
+ WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
+ if (w->withObject)
+ w->withObject->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
+ g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_SimpleCallContext:
+ break;
+ case Heap::ExecutionContext::Type_CallContext: {
QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
ctx->callData->thisObject.mark(engine);
for (int arg = 0; arg < qMax(ctx->callData->argc, (int)c->function->formalParameterCount()); ++arg)
@@ -264,17 +314,13 @@ void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
if (c->activation)
c->activation->mark(engine);
c->function->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_WithContext) {
- WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
- if (w->withObject)
- w->withObject->mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_CatchContext) {
- CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
- c->exceptionVarName->mark(engine);
- c->exceptionValue.mark(engine);
- } else if (ctx->type == Heap::ExecutionContext::Type_GlobalContext) {
- GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
- g->global->mark(engine);
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ QmlContext::Data *g = static_cast<QmlContext::Data *>(ctx);
+ g->qml->mark(engine);
+ break;
+ }
}
}
@@ -282,57 +328,71 @@ void ExecutionContext::setProperty(String *name, const Value &value)
{
Scope scope(this);
ScopedContext ctx(scope, this);
+ ScopedObject activation(scope);
+
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ activation = (Object *)0;
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d())) {
+ c->exceptionValue = value;
+ return;
+ }
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (w->hasProperty(name)) {
w->put(name, value);
return;
}
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name)) {
- static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = value;
- return;
- } else {
- ScopedObject activation(scope, (Object *)0);
- if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
- Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
- if (c->function->function) {
- uint index = c->function->function->internalClass->find(name);
- if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount()) {
- c->callData->args[c->function->formalParameterCount() - index - 1] = value;
- } else {
- index -= c->function->formalParameterCount();
- c->locals[index] = value;
- }
- return;
+ break;
+ }
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
+ break;
+ }
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ if (c->function->function) {
+ uint index = c->function->function->internalClass->find(name);
+ if (index < UINT_MAX) {
+ if (index < c->function->formalParameterCount()) {
+ c->callData->args[c->function->formalParameterCount() - index - 1] = value;
+ } else {
+ index -= c->function->formalParameterCount();
+ c->locals[index] = value;
}
+ return;
}
- activation = c->activation;
- } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
}
+ activation = c->activation;
+ break;
+ }
+ case Heap::ExecutionContext::Type_QmlContext: {
+ activation = static_cast<Heap::QmlContext *>(ctx->d())->qml;
+ activation->put(name, value);
+ return;
+ }
+ }
- if (activation) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) {
- activation->put(name, value);
- return;
- } else {
- uint member = activation->internalClass()->find(name);
- if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
- return;
- }
- }
+ if (activation) {
+ uint member = activation->internalClass()->find(name);
+ if (member < UINT_MAX) {
+ activation->putValue(member, value);
+ return;
}
}
}
- if (d()->strictMode || name->equals(d()->engine->id_this)) {
+
+ if (d()->strictMode || name->equals(d()->engine->id_this())) {
ScopedValue n(scope, name->asReturnedValue());
engine()->throwReferenceError(n);
return;
}
- d()->engine->globalObject()->put(name, value);
+ d()->engine->globalObject->put(name, value);
}
ReturnedValue ExecutionContext::getProperty(String *name)
@@ -341,14 +401,22 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ScopedValue v(scope);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
@@ -356,17 +424,18 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (hasProperty) {
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
@@ -387,85 +456,97 @@ ReturnedValue ExecutionContext::getProperty(String *name)
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
+ v = qml->get(name, &hasProperty);
if (hasProperty)
return v->asReturnedValue();
+ break;
+ }
}
}
ScopedValue n(scope, name);
return engine()->throwReferenceError(n);
}
-ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
{
Scope scope(this);
ScopedValue v(scope);
- *base = (Heap::Object *)0;
+ base->setM(0);
name->makeIdentifier(scope.engine);
- if (name->equals(d()->engine->id_this))
+ if (name->equals(d()->engine->id_this()))
return thisObject().asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
ScopedContext ctx(scope, this);
for (; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ switch (ctx->d()->type) {
+ case Heap::ExecutionContext::Type_CatchContext: {
+ hasCatchScope = true;
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name->d()))
+ return c->exceptionValue.asReturnedValue();
+ break;
+ }
+ case Heap::ExecutionContext::Type_WithContext: {
ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
if (hasProperty) {
- *base = w->d();
+ base->setM(w->d());
return v->asReturnedValue();
}
- continue;
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
- hasCatchScope = true;
- Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ case Heap::ExecutionContext::Type_GlobalContext: {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ bool hasProperty = false;
+ v = global->get(name, &hasProperty);
+ if (hasProperty)
+ return v->asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ case Heap::ExecutionContext::Type_CallContext:
+ case Heap::ExecutionContext::Type_SimpleCallContext: {
Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < f->formalParameterCount())
- return c->callData->args[f->formalParameterCount() - index - 1].asReturnedValue();
- return c->locals[index - f->formalParameterCount()].asReturnedValue();
+ if (index < c->function->formalParameterCount())
+ return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
}
}
ScopedObject activation(scope, c->activation);
if (activation) {
bool hasProperty = false;
v = activation->get(name, &hasProperty);
- if (hasProperty) {
- if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext)
- *base = activation->d();
+ if (hasProperty)
return v->asReturnedValue();
- }
}
if (f->function() && f->function()->isNamedExpression()
&& name->equals(ScopedString(scope, f->function()->name())))
- return c->function->asReturnedValue();
+ return f.asReturnedValue();
+ break;
}
-
- else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
- ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ case Heap::ExecutionContext::Type_QmlContext: {
+ ScopedObject qml(scope, static_cast<Heap::QmlContext *>(ctx->d())->qml);
bool hasProperty = false;
- v = global->get(name, &hasProperty);
- if (hasProperty)
+ v = qml->get(name, &hasProperty);
+ if (hasProperty) {
+ base->setM(qml->d());
return v->asReturnedValue();
+ }
+ break;
+ }
}
}
ScopedValue n(scope, name);
@@ -476,7 +557,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())
@@ -487,3 +568,19 @@ Heap::FunctionObject *ExecutionContext::getFunctionObject() const
return 0;
}
+
+
+QObject *QmlContext::qmlScope() const
+{
+ return d()->qml->scopeObject;
+}
+
+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 8392dd836d..6c360e7dda 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -33,11 +33,25 @@
#ifndef QMLJS_ENVIRONMENT_H
#define QMLJS_ENVIRONMENT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
+class QQmlContextData;
+class QObject;
+
namespace QV4 {
namespace CompiledData {
@@ -45,6 +59,8 @@ struct CompilationUnit;
struct Function;
}
+struct QmlContextWrapper;
+struct Identifier;
struct CallContext;
struct CatchContext;
struct WithContext;
@@ -74,9 +90,9 @@ struct ExecutionContext : Base {
Type_GlobalContext = 0x1,
Type_CatchContext = 0x2,
Type_WithContext = 0x3,
- Type_SimpleCallContext = 0x4,
- Type_CallContext = 0x5,
- Type_QmlContext = 0x6
+ Type_QmlContext = 0x4,
+ Type_SimpleCallContext = 0x5,
+ Type_CallContext = 0x6
};
inline ExecutionContext(ExecutionEngine *engine, ContextType t);
@@ -84,8 +100,7 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- ExecutionContext *parent;
- ExecutionContext *outer;
+ Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -94,6 +109,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)
@@ -102,29 +129,34 @@ struct CallContext : ExecutionContext {
locals = 0;
activation = 0;
}
- CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function);
- FunctionObject *function;
+ Pointer<FunctionObject> function;
Value *locals;
- Object *activation;
+ Pointer<Object> activation;
};
struct GlobalContext : ExecutionContext {
GlobalContext(ExecutionEngine *engine);
- Object *global;
+ Pointer<Object> global;
};
struct CatchContext : ExecutionContext {
- CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue);
- StringValue exceptionVarName;
+ CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
+ Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
- WithContext(ExecutionEngine *engine, QV4::Object *with);
- Object *withObject;
+ WithContext(ExecutionContext *outerContext, Object *with);
+ Pointer<Object> withObject;
};
+struct QmlContextWrapper;
+
+struct QmlContext : ExecutionContext {
+ QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml);
+ Pointer<QmlContextWrapper> qml;
+};
}
@@ -139,16 +171,17 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
- Heap::CallContext *newCallContext(FunctionObject *f, CallData *callData);
- Heap::WithContext *newWithContext(Object *with);
- Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
- Heap::CallContext *newQmlContext(FunctionObject *f, Object *qml);
+ Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
+ 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);
void setProperty(String *name, const Value &value);
ReturnedValue getProperty(String *name);
- ReturnedValue getPropertyAndBase(String *name, Heap::Object **base);
+ ReturnedValue getPropertyAndBase(String *name, Value *base);
bool deleteProperty(String *name);
inline CallContext *asCallContext();
@@ -160,7 +193,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
static void markObjects(Heap::Base *m, ExecutionEngine *e);
- const Value &thisObject() const {
+ Value &thisObject() const {
return d()->callData->thisObject;
}
int argc() const {
@@ -174,7 +207,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
}
};
-struct CallContext : public ExecutionContext
+struct Q_QML_EXPORT CallContext : public ExecutionContext
{
V4_MANAGED(CallContext, ExecutionContext)
@@ -208,6 +241,16 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
+struct QmlContext : public ExecutionContext
+{
+ V4_MANAGED(QmlContext, ExecutionContext)
+
+ QObject *qmlScope() const;
+ QQmlContextData *qmlContext() const;
+
+ void takeContextOwnership();
+};
+
inline CallContext *ExecutionContext::asCallContext()
{
return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index 8a66c2cbfc..8901834e76 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -33,6 +33,7 @@
#include "qv4dataview_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include "qendian.h"
@@ -46,9 +47,9 @@ Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
+ Scope scope(static_cast<const Object *>(m)->engine());
Scoped<ArrayBuffer> buffer(scope, callData->argument(0));
if (!buffer)
return scope.engine->throwTypeError();
@@ -61,7 +62,7 @@ ReturnedValue DataViewCtor::construct(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;
@@ -69,21 +70,12 @@ ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
}
-ReturnedValue DataViewCtor::call(Managed *that, CallData *callData)
+ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
-Heap::DataView::DataView(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->dataViewPrototype.asObject()),
- buffer(0),
- byteLength(0),
- byteOffset(0)
-{
-}
-
-
void DataView::markObjects(Heap::Base *that, ExecutionEngine *e)
{
DataView::Data *v = static_cast<DataView::Data *>(that);
@@ -94,30 +86,38 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
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 3f0c1e9e23..26347766d3 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -33,6 +33,17 @@
#ifndef QV4DATAVIEW_H
#define QV4DATAVIEW_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
@@ -47,8 +58,8 @@ struct DataViewCtor : FunctionObject {
};
struct DataView : Object {
- DataView(ExecutionEngine *e);
- ArrayBuffer *buffer;
+ DataView() {}
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
};
@@ -59,13 +70,14 @@ struct DataViewCtor: FunctionObject
{
V4_OBJECT2(DataViewCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
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 451ef2486d..a6e1f47d91 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -36,6 +36,7 @@
#include "qv4objectproto_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
@@ -627,15 +628,14 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
- : Heap::Object(engine->emptyClass, engine->datePrototype.asObject())
+Heap::DateObject::DateObject(const QDateTime &date)
{
- value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
+ this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN();
}
QDateTime DateObject::toQDateTime() const
{
- return ToDateTime(date().asDouble(), Qt::LocalTime);
+ return ToDateTime(date(), Qt::LocalTime);
}
DEFINE_OBJECT_VTABLE(DateCtor);
@@ -645,9 +645,9 @@ Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DateCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<DateCtor *>(m)->engine());
+ Scope scope(static_cast<const DateCtor *>(m)->engine());
double t = 0;
if (callData->argc == 0)
@@ -655,15 +655,16 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
else if (callData->argc == 1) {
ScopedValue arg(scope, callData->args[0]);
- if (DateObject *d = arg->asDateObject())
- arg = d->date();
- else
+ if (DateObject *d = arg->as<DateObject>()) {
+ t = d->date();
+ } else {
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
- if (arg->isString())
- t = ParseString(arg->stringValue()->toQString());
- else
- t = TimeClip(arg->toNumber());
+ if (arg->isString())
+ t = ParseString(arg->stringValue()->toQString());
+ else
+ t = TimeClip(arg->toNumber());
+ }
}
else { // d.argc > 1
@@ -683,18 +684,18 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
return Encode(scope.engine->newDateObject(Primitive::fromDouble(t)));
}
-ReturnedValue DateCtor::call(Managed *m, CallData *)
+ReturnedValue DateCtor::call(const Managed *m, CallData *)
{
double t = currentTime();
- return static_cast<DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
+ return static_cast<const DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue();
}
void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(7));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(7));
LocalTZA = getLocalTZA();
ctor->defineDefaultProperty(QStringLiteral("parse"), method_parse, 1);
@@ -702,13 +703,13 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("now"), method_now, 0);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toDateString"), method_toDateString, 0);
defineDefaultProperty(QStringLiteral("toTimeString"), method_toTimeString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString, 0);
defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString, 0);
- defineDefaultProperty(engine->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("getTime"), method_getTime, 0);
defineDefaultProperty(QStringLiteral("getYear"), method_getYear, 0);
defineDefaultProperty(QStringLiteral("getFullYear"), method_getFullYear, 0);
@@ -752,8 +753,8 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
double DatePrototype::getThisDate(ExecutionContext *ctx)
{
- if (DateObject *thisObject = ctx->thisObject().asDateObject())
- return thisObject->date().asDouble();
+ if (DateObject *thisObject = ctx->thisObject().as<DateObject>())
+ return thisObject->date();
else {
ctx->engine()->throwTypeError();
return 0;
@@ -994,8 +995,8 @@ ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
return ctx->engine()->throwTypeError();
double t = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(t));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(t));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
@@ -1005,175 +1006,175 @@ ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
- return self->date().asReturnedValue();
+ self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber();
double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber();
double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber();
double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber();
t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber();
t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (std::isnan(t))
t = 0;
else
@@ -1189,49 +1190,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
r = UTC(MakeDate(r, TimeWithinDay(t)));
r = TimeClip(r);
}
- self->date().setDouble(r);
- return self->date().asReturnedValue();
+ self->setDate(r);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = LocalTime(self->date().asDouble());
+ double t = LocalTime(self->date());
if (std::isnan(t))
t = 0;
double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN();
double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber();
double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
- self->date().setDouble(t);
- return self->date().asReturnedValue();
+ self->setDate(t);
+ return Encode(self->date());
}
ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
}
@@ -1250,11 +1251,11 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
{
- DateObject *self = ctx->thisObject().asDateObject();
+ DateObject *self = ctx->thisObject().as<DateObject>();
if (!self)
return ctx->engine()->throwTypeError();
- double t = self->date().asDouble();
+ double t = self->date();
if (!std::isfinite(t))
return ctx->engine()->throwRangeError(ctx->thisObject());
@@ -1297,7 +1298,7 @@ ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
ScopedValue v(scope, O->objectValue()->get(s));
- FunctionObject *toIso = v->asFunctionObject();
+ FunctionObject *toIso = v->as<FunctionObject>();
if (!toIso)
return ctx->engine()->throwTypeError();
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index dad3689054..2eaa837666 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4DATEOBJECT_P_H
#define QV4DATEOBJECT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -46,21 +57,20 @@ namespace QV4 {
namespace Heap {
struct DateObject : Object {
- DateObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype)
+ DateObject()
{
- value = Encode(qSNaN());
+ date = qSNaN();
}
- DateObject(QV4::ExecutionEngine *engine, const Value &date)
- : Object(engine->emptyClass, engine->datePrototype.asObject())
+ DateObject(const Value &date)
{
- value = date;
+ this->date = date.toNumber();
}
- DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
- Value value;
+ DateObject(const QDateTime &date);
+ double date;
};
+
struct DateCtor : FunctionObject {
DateCtor(QV4::ExecutionContext *scope);
};
@@ -70,21 +80,26 @@ struct DateCtor : FunctionObject {
struct DateObject: Object {
V4_OBJECT2(DateObject, Object)
Q_MANAGED_TYPE(DateObject)
+ V4_PROTOTYPE(datePrototype)
- Value date() const { return d()->value; }
- Value &date() { return d()->value; }
- void setDate(const Value &date) { d()->value = date; }
+ double date() const { return d()->date; }
+ void setDate(double date) { d()->date = date; }
QDateTime toQDateTime() const;
};
+template<>
+inline const DateObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : 0;
+}
+
struct DateCtor: FunctionObject
{
V4_OBJECT2(DateCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *);
};
struct DatePrototype: DateObject
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 36e7a3558c..7706a40da6 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -38,69 +38,72 @@
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
#include "qv4script_p.h"
-#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
-#include <iostream>
+#include "qv4string_p.h"
+#include "qv4objectiterator_p.h"
+#include <iostream>
#include <algorithm>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonValue>
+
+QT_BEGIN_NAMESPACE
+
using namespace QV4;
using namespace QV4::Debugging;
-namespace {
-class JavaScriptJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- int frameNr;
- const QString &script;
+V4Debugger::JavaScriptJob::JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr,
+ const QString &script)
+ : engine(engine)
+ , frameNr(frameNr)
+ , script(script)
+ , resultIsException(false)
+{}
-public:
- JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script)
- : engine(engine)
- , frameNr(frameNr)
- , script(script)
- {}
-
- void run()
- {
- Scope scope(engine);
+void V4Debugger::JavaScriptJob::run()
+{
+ Scope scope(engine);
- ExecutionContextSaver saver(scope, engine->currentContext());
+ ExecutionContextSaver saver(scope);
- if (frameNr > 0) {
- Value *savedContexts = scope.alloc(frameNr);
- for (int i = 0; i < frameNr; ++i) {
- savedContexts[i] = engine->currentContext();
- engine->popContext();
- }
+ ExecutionContext *ctx = engine->currentContext;
+ if (frameNr > 0) {
+ for (int i = 0; i < frameNr; ++i) {
+ 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
- // is a side-effect of inheritContext.
- script.inheritContext = true;
- script.parse();
- QV4::ScopedValue result(scope);
- if (!scope.engine->hasException)
- result = script.run();
- if (scope.engine->hasException)
- result = scope.engine->catchException();
- handleResult(result);
+ 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
+ // is a side-effect of inheritContext.
+ script.inheritContext = true;
+ script.parse();
+ QV4::ScopedValue result(scope);
+ if (!scope.engine->hasException)
+ result = script.run();
+ if (scope.engine->hasException) {
+ result = scope.engine->catchException();
+ resultIsException = true;
}
+ handleResult(result);
+}
-protected:
- virtual void handleResult(QV4::ScopedValue &result) = 0;
-};
+bool V4Debugger::JavaScriptJob::hasExeption() const
+{
+ return resultIsException;
+}
-class EvalJob: public JavaScriptJob
+class EvalJob: public V4Debugger::JavaScriptJob
{
bool result;
public:
EvalJob(QV4::ExecutionEngine *engine, const QString &script)
- : JavaScriptJob(engine, /*frameNr*/-1, script)
+ : V4Debugger::JavaScriptJob(engine, /*frameNr*/-1, script)
, result(false)
{}
@@ -115,58 +118,8 @@ public:
}
};
-class ExpressionEvalJob: public JavaScriptJob
-{
- Debugger::Collector *collector;
-
-public:
- ExpressionEvalJob(ExecutionEngine *engine, int frameNr, const QString &expression, Debugger::Collector *collector)
- : JavaScriptJob(engine, frameNr, expression)
- , collector(collector)
- {
- }
-
- virtual void handleResult(QV4::ScopedValue &result)
- {
- collector->collect(QStringLiteral("body"), result);
- }
-};
-
-class GatherSourcesJob: public Debugger::Job
-{
- QV4::ExecutionEngine *engine;
- const int seq;
-
-public:
- GatherSourcesJob(QV4::ExecutionEngine *engine, int seq)
- : engine(engine)
- , seq(seq)
- {}
-
- ~GatherSourcesJob() {}
-
- void run()
- {
- QStringList sources;
-
- foreach (QV4::CompiledData::CompilationUnit *unit, engine->compilationUnits) {
- QString fileName = unit->fileName();
- if (!fileName.isEmpty())
- sources.append(fileName);
- }
-
- Debugger *debugger = engine->debugger;
- QMetaObject::invokeMethod(debugger->agent(), "sourcesCollected", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, debugger),
- Q_ARG(QStringList, sources),
- Q_ARG(int, seq));
- }
-};
-}
-
-Debugger::Debugger(QV4::ExecutionEngine *engine)
+V4Debugger::V4Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
- , m_agent(0)
, m_state(Running)
, m_stepping(NotStepping)
, m_pauseRequested(false)
@@ -176,46 +129,11 @@ Debugger::Debugger(QV4::ExecutionEngine *engine)
, m_gatherSources(0)
, m_runningJob(0)
{
- qMetaTypeId<Debugger*>();
+ qMetaTypeId<V4Debugger*>();
qMetaTypeId<PauseReason>();
}
-Debugger::~Debugger()
-{
- detachFromAgent();
-}
-
-void Debugger::attachToAgent(DebuggerAgent *agent)
-{
- Q_ASSERT(!m_agent);
- m_agent = agent;
-}
-
-void Debugger::detachFromAgent()
-{
- DebuggerAgent *agent = 0;
- {
- QMutexLocker locker(&m_lock);
- agent = m_agent;
- m_agent = 0;
- }
- if (agent)
- agent->removeDebugger(this);
-}
-
-void Debugger::gatherSources(int requestSequenceNr)
-{
- QMutexLocker locker(&m_lock);
-
- m_gatherSources = new GatherSourcesJob(m_engine, requestSequenceNr);
- if (m_state == Paused) {
- runInEngine_havingLock(m_gatherSources);
- delete m_gatherSources;
- m_gatherSources = 0;
- }
-}
-
-void Debugger::pause()
+void V4Debugger::pause()
{
QMutexLocker locker(&m_lock);
if (m_state == Paused)
@@ -223,7 +141,7 @@ void Debugger::pause()
m_pauseRequested = true;
}
-void Debugger::resume(Speed speed)
+void V4Debugger::resume(Speed speed)
{
QMutexLocker locker(&m_lock);
if (m_state != Paused)
@@ -232,292 +150,47 @@ 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();
}
-void Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
+void V4Debugger::addBreakPoint(const QString &fileName, int lineNumber, const QString &condition)
{
QMutexLocker locker(&m_lock);
m_breakPoints.insert(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber), condition);
m_haveBreakPoints = true;
}
-void Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
+void V4Debugger::removeBreakPoint(const QString &fileName, int lineNumber)
{
QMutexLocker locker(&m_lock);
m_breakPoints.remove(DebuggerBreakPoint(fileName.mid(fileName.lastIndexOf('/') + 1), lineNumber));
m_haveBreakPoints = !m_breakPoints.isEmpty();
}
-void Debugger::setBreakOnThrow(bool onoff)
+void V4Debugger::setBreakOnThrow(bool onoff)
{
QMutexLocker locker(&m_lock);
m_breakOnThrow = onoff;
}
-Debugger::ExecutionState Debugger::currentExecutionState() const
+V4Debugger::ExecutionState V4Debugger::currentExecutionState() const
{
ExecutionState state;
state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->currentContext()->lineNumber;
+ state.lineNumber = engine()->current->lineNumber;
return state;
}
-QVector<StackFrame> Debugger::stackTrace(int frameLimit) const
+QVector<StackFrame> V4Debugger::stackTrace(int frameLimit) const
{
return m_engine->stackTrace(frameLimit);
}
-static inline Heap::CallContext *findContext(Heap::ExecutionContext *ctxt, int frame)
-{
- if (!ctxt)
- return 0;
-
- Scope scope(ctxt->engine);
- ScopedContext ctx(scope, ctxt);
- while (ctx) {
- CallContext *cCtxt = ctx->asCallContext();
- if (cCtxt && cCtxt->d()->function) {
- if (frame < 1)
- return cCtxt->d();
- --frame;
- }
- ctx = ctx->d()->parent;
- }
-
- return 0;
-}
-
-static inline Heap::CallContext *findScope(Heap::ExecutionContext *ctxt, int scope)
-{
- if (!ctxt)
- return 0;
-
- Scope s(ctxt->engine);
- ScopedContext ctx(s, ctxt);
- for (; scope > 0 && ctx; --scope)
- ctx = ctx->d()->outer;
-
- return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
-}
-
-void Debugger::collectArgumentsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class ArgumentCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- ArgumentCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- ~ArgumentCollectJob() {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- int nFormals = ctxt->formalCount();
- for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->formals()[nFormals - i - 1])
- qName = name->string;
- v = ctxt->argument(i);
- collector->collect(qName, v);
- }
- }
- };
-
- ArgumentCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-/// Same as \c retrieveArgumentsFromContext, but now for locals.
-void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int scopeNr)
-{
- if (state() != Paused)
- return;
-
- class LocalCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- int scopeNr;
-
- public:
- LocalCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, int scopeNr)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , scopeNr(scopeNr)
- {}
-
- void run()
- {
- if (frameNr < 0)
- return;
-
- Scope scope(engine);
- Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
- if (!ctxt)
- return;
-
- ScopedValue v(scope);
- for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
- QString qName;
- if (Identifier *name = ctxt->variables()[i])
- qName = name->string;
- v = ctxt->d()->locals[i];
- collector->collect(qName, v);
- }
- }
- };
-
- LocalCollectJob job(m_engine, collector, frameNr, scopeNr);
- runInEngine(&job);
-}
-
-bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
-{
- if (state() != Paused)
- return false;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
- int frameNr;
- bool *foundThis;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector, int frameNr, bool *foundThis)
- : engine(engine)
- , collector(collector)
- , frameNr(frameNr)
- , foundThis(foundThis)
- {}
-
- void run()
- {
- *foundThis = myRun();
- }
-
- bool myRun()
- {
- Scope scope(engine);
- ScopedContext ctxt(scope, findContext(engine->currentContext(), frameNr));
- while (ctxt) {
- if (CallContext *cCtxt = ctxt->asCallContext())
- if (cCtxt->d()->activation)
- break;
- ctxt = ctxt->d()->outer;
- }
-
- if (!ctxt)
- return false;
-
- ScopedObject o(scope, ctxt->asCallContext()->d()->activation);
- collector->collect(o);
- return true;
- }
- };
-
- bool foundThis = false;
- ThisCollectJob job(m_engine, collector, frame, &foundThis);
- runInEngine(&job);
- return foundThis;
-}
-
-void Debugger::collectThrownValue(Collector *collector)
-{
- if (state() != Paused || !m_engine->hasException)
- return;
-
- class ThisCollectJob: public Job
- {
- QV4::ExecutionEngine *engine;
- Collector *collector;
-
- public:
- ThisCollectJob(QV4::ExecutionEngine *engine, Collector *collector)
- : engine(engine)
- , collector(collector)
- {}
-
- void run()
- {
- Scope scope(engine);
- ScopedValue v(scope, engine->exceptionValue);
- collector->collect(QStringLiteral("exception"), v);
- }
- };
-
- ThisCollectJob job(m_engine, collector);
- runInEngine(&job);
-}
-
-void Debugger::collectReturnedValue(Collector *collector) const
-{
- if (state() != Paused)
- return;
-
- Scope scope(m_engine);
- ScopedObject o(scope, m_returnedValue.valueRef());
- collector->collect(o);
-}
-
-QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
-{
- QVector<Heap::ExecutionContext::ContextType> types;
-
- if (state() != Paused)
- return types;
-
- Scope scope(m_engine);
- Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame));
- if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext)
- return types;
-
- ScopedContext it(scope, sctxt->d());
- for (; it; it = it->d()->outer)
- types.append(it->d()->type);
-
- return types;
-}
-
-
-void Debugger::evaluateExpression(int frameNr, const QString &expression, Debugger::Collector *resultsCollector)
-{
- Q_ASSERT(state() == Paused);
-
- Q_ASSERT(m_runningJob == 0);
- ExpressionEvalJob job(m_engine, frameNr, expression, resultsCollector);
- runInEngine(&job);
-}
-
-void Debugger::maybeBreakAtInstruction()
+void V4Debugger::maybeBreakAtInstruction()
{
if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
return;
@@ -532,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:
@@ -548,25 +221,25 @@ 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);
}
}
}
-void Debugger::enteringFunction()
+void V4Debugger::enteringFunction()
{
if (m_runningJob)
return;
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, m_engine->currentContext());
+ m_currentContext.set(m_engine, *m_engine->currentContext);
}
}
-void Debugger::leavingFunction(const ReturnedValue &retVal)
+void V4Debugger::leavingFunction(const ReturnedValue &retVal)
{
if (m_runningJob)
return;
@@ -574,14 +247,14 @@ 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);
}
}
-void Debugger::aboutToThrow()
+void V4Debugger::aboutToThrow()
{
if (!m_breakOnThrow)
return;
@@ -593,10 +266,10 @@ void Debugger::aboutToThrow()
pauseAndWait(Throwing);
}
-Function *Debugger::getFunction() const
+Function *V4Debugger::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();
@@ -604,15 +277,13 @@ Function *Debugger::getFunction() const
return context->d()->engine->globalCode;
}
-void Debugger::pauseAndWait(PauseReason reason)
+void V4Debugger::pauseAndWait(PauseReason reason)
{
if (m_runningJob)
return;
m_state = Paused;
- QMetaObject::invokeMethod(m_agent, "debuggerPaused", Qt::QueuedConnection,
- Q_ARG(QV4::Debugging::Debugger*, this),
- Q_ARG(QV4::Debugging::PauseReason, reason));
+ emit debuggerPaused(this, reason);
while (true) {
m_runningCondition.wait(&m_lock);
@@ -627,7 +298,7 @@ void Debugger::pauseAndWait(PauseReason reason)
m_state = Running;
}
-bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
+bool V4Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
{
BreakPoints::iterator it = m_breakPoints.find(DebuggerBreakPoint(filename.mid(filename.lastIndexOf('/') + 1), linenr));
if (it == m_breakPoints.end())
@@ -645,13 +316,13 @@ bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
return evilJob.resultAsBoolean();
}
-void Debugger::runInEngine(Debugger::Job *job)
+void V4Debugger::runInEngine(V4Debugger::Job *job)
{
QMutexLocker locker(&m_lock);
runInEngine_havingLock(job);
}
-void Debugger::runInEngine_havingLock(Debugger::Job *job)
+void V4Debugger::runInEngine_havingLock(V4Debugger::Job *job)
{
Q_ASSERT(job);
Q_ASSERT(m_runningJob == 0);
@@ -662,174 +333,8 @@ void Debugger::runInEngine_havingLock(Debugger::Job *job)
m_runningJob = 0;
}
-void DebuggerAgent::addDebugger(Debugger *debugger)
-{
- Q_ASSERT(!m_debuggers.contains(debugger));
- m_debuggers << debugger;
- debugger->attachToAgent(this);
-
- debugger->setBreakOnThrow(m_breakOnThrow);
-
- foreach (const BreakPoint &breakPoint, m_breakPoints.values())
- if (breakPoint.enabled)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
-}
-
-void DebuggerAgent::removeDebugger(Debugger *debugger)
-{
- m_debuggers.removeAll(debugger);
- debugger->detachFromAgent();
-}
-
-void DebuggerAgent::pause(Debugger *debugger) const
-{
- debugger->pause();
-}
-
-void DebuggerAgent::pauseAll() const
+V4Debugger::Job::~Job()
{
- foreach (Debugger *debugger, m_debuggers)
- pause(debugger);
}
-void DebuggerAgent::resumeAll() const
-{
- foreach (Debugger *debugger, m_debuggers)
- if (debugger->state() == Debugger::Paused)
- debugger->resume(Debugger::FullThrottle);
-}
-
-int DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber, bool enabled, const QString &condition)
-{
- if (enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->addBreakPoint(fileName, lineNumber, condition);
-
- int id = m_breakPoints.size();
- m_breakPoints.insert(id, BreakPoint(fileName, lineNumber, enabled, condition));
- return id;
-}
-
-void DebuggerAgent::removeBreakPoint(int id)
-{
- BreakPoint breakPoint = m_breakPoints.value(id);
- if (!breakPoint.isValid())
- return;
-
- m_breakPoints.remove(id);
-
- if (breakPoint.enabled)
- foreach (Debugger *debugger, m_debuggers)
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
-}
-
-void DebuggerAgent::removeAllBreakPoints()
-{
- QList<int> ids = m_breakPoints.keys();
- foreach (int id, ids)
- removeBreakPoint(id);
-}
-
-void DebuggerAgent::enableBreakPoint(int id, bool onoff)
-{
- BreakPoint &breakPoint = m_breakPoints[id];
- if (!breakPoint.isValid() || breakPoint.enabled == onoff)
- return;
- breakPoint.enabled = onoff;
-
- foreach (Debugger *debugger, m_debuggers) {
- if (onoff)
- debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
- else
- debugger->removeBreakPoint(breakPoint.fileName, breakPoint.lineNr);
- }
-}
-
-QList<int> DebuggerAgent::breakPointIds(const QString &fileName, int lineNumber) const
-{
- QList<int> ids;
-
- for (QHash<int, BreakPoint>::const_iterator i = m_breakPoints.begin(), ei = m_breakPoints.end(); i != ei; ++i)
- if (i->lineNr == lineNumber && fileName.endsWith(i->fileName))
- ids.push_back(i.key());
-
- return ids;
-}
-
-void DebuggerAgent::setBreakOnThrow(bool onoff)
-{
- if (onoff != m_breakOnThrow) {
- m_breakOnThrow = onoff;
- foreach (Debugger *debugger, m_debuggers)
- debugger->setBreakOnThrow(onoff);
- }
-}
-
-DebuggerAgent::~DebuggerAgent()
-{
- foreach (Debugger *debugger, m_debuggers)
- debugger->detachFromAgent();
-
- Q_ASSERT(m_debuggers.isEmpty());
-}
-
-Debugger::Collector::~Collector()
-{
-}
-
-void Debugger::Collector::collect(const QString &name, const ScopedValue &value)
-{
- switch (value->type()) {
- case Value::Empty_Type:
- Q_ASSERT(!"empty Value encountered");
- break;
- case Value::Undefined_Type:
- addUndefined(name);
- break;
- case Value::Null_Type:
- addNull(name);
- break;
- case Value::Boolean_Type:
- addBoolean(name, value->booleanValue());
- break;
- case Value::Managed_Type:
- if (String *s = value->asString())
- addString(name, s->toQString());
- else
- addObject(name, value);
- break;
- case Value::Integer_Type:
- addInteger(name, value->int_32);
- break;
- default: // double
- addDouble(name, value->doubleValue());
- break;
- }
-}
-
-void Debugger::Collector::collect(Object *object)
-{
- bool property = true;
- qSwap(property, m_isProperty);
-
- Scope scope(m_engine);
- ObjectIterator it(scope, object, ObjectIterator::EnumerableOnly);
- ScopedValue name(scope);
- ScopedValue value(scope);
- while (true) {
- Value v;
- name = it.nextPropertyNameAsString(&v);
- if (name->isNull())
- break;
- QString key = name->toQStringNoThrow();
- value = v;
- collect(key, value);
- }
-
- qSwap(property, m_isProperty);
-}
-
-
-Debugger::Job::~Job()
-{
-}
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index e6a9750351..fdc9cac24f 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -34,6 +34,17 @@
#ifndef DEBUGGING_H
#define DEBUGGING_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4context_p.h"
@@ -44,6 +55,8 @@
#include <QMutex>
#include <QWaitCondition>
+#include <QtCore/QJsonObject>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -59,8 +72,6 @@ enum PauseReason {
Step
};
-class DebuggerAgent;
-
struct DebuggerBreakPoint {
DebuggerBreakPoint(const QString &fileName, int line)
: fileName(fileName), lineNumber(line)
@@ -79,43 +90,44 @@ inline bool operator==(const DebuggerBreakPoint &a, const DebuggerBreakPoint &b)
typedef QHash<DebuggerBreakPoint, QString> BreakPoints;
+class Q_QML_EXPORT Debugger : public QObject
+{
+ Q_OBJECT
-class Q_QML_EXPORT Debugger
+public:
+ virtual ~Debugger() {}
+ virtual bool pauseAtNextOpportunity() const = 0;
+ virtual void maybeBreakAtInstruction() = 0;
+ virtual void enteringFunction() = 0;
+ virtual void leavingFunction(const ReturnedValue &retVal) = 0;
+ virtual void aboutToThrow() = 0;
+};
+
+class Q_QML_EXPORT V4Debugger : public Debugger
{
+ Q_OBJECT
public:
- class Job
+ class Q_QML_EXPORT Job
{
public:
virtual ~Job() = 0;
virtual void run() = 0;
};
- class Q_QML_EXPORT Collector
+ class Q_QML_EXPORT JavaScriptJob: public Job
{
- public:
- Collector(ExecutionEngine *engine): m_engine(engine), m_isProperty(false) {}
- virtual ~Collector();
+ QV4::ExecutionEngine *engine;
+ int frameNr;
+ const QString &script;
+ bool resultIsException;
- void collect(const QString &name, const ScopedValue &value);
- void collect(Object *object);
+ public:
+ JavaScriptJob(QV4::ExecutionEngine *engine, int frameNr, const QString &script);
+ void run();
+ bool hasExeption() const;
protected:
- virtual void addUndefined(const QString &name) = 0;
- virtual void addNull(const QString &name) = 0;
- virtual void addBoolean(const QString &name, bool value) = 0;
- virtual void addString(const QString &name, const QString &value) = 0;
- virtual void addObject(const QString &name, const Value &value) = 0;
- virtual void addInteger(const QString &name, int value) = 0;
- virtual void addDouble(const QString &name, double value) = 0;
-
- QV4::ExecutionEngine *engine() const { return m_engine; }
-
- bool isProperty() const { return m_isProperty; }
- void setIsProperty(bool onoff) { m_isProperty = onoff; }
-
- private:
- QV4::ExecutionEngine *m_engine;
- bool m_isProperty;
+ virtual void handleResult(QV4::ScopedValue &result) = 0;
};
enum State {
@@ -132,17 +144,11 @@ public:
NotStepping = FullThrottle
};
- Debugger(ExecutionEngine *engine);
- ~Debugger();
+ V4Debugger(ExecutionEngine *engine);
ExecutionEngine *engine() const
{ return m_engine; }
- void attachToAgent(DebuggerAgent *agent);
- void detachFromAgent();
- DebuggerAgent *agent() const { return m_agent; }
-
- void gatherSources(int requestSequenceNr);
void pause();
void resume(Speed speed);
@@ -166,14 +172,10 @@ public:
}
QVector<StackFrame> stackTrace(int frameLimit = -1) const;
- void collectArgumentsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- void collectLocalsInContext(Collector *collector, int frameNr = 0, int scopeNr = 0);
- bool collectThisInContext(Collector *collector, int frame = 0);
- void collectThrownValue(Collector *collector);
- void collectReturnedValue(Collector *collector) const;
QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
- void evaluateExpression(int frameNr, const QString &expression, Collector *resultsCollector);
+ Function *getFunction() const;
+ void runInEngine(Job *job);
public: // compile-time interface
void maybeBreakAtInstruction();
@@ -183,21 +185,19 @@ public: // execution hooks
void leavingFunction(const ReturnedValue &retVal);
void aboutToThrow();
-private:
- Function *getFunction() const;
+signals:
+ void sourcesCollected(QV4::Debugging::V4Debugger *self, const QStringList &sources, int seq);
+ void debuggerPaused(QV4::Debugging::V4Debugger *self, QV4::Debugging::PauseReason reason);
+private:
// requires lock to be held
void pauseAndWait(PauseReason reason);
-
bool reallyHitTheBreakPoint(const QString &filename, int linenr);
-
- void runInEngine(Job *job);
- void runInEngine_havingLock(Debugger::Job *job);
+ void runInEngine_havingLock(V4Debugger::Job *job);
private:
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_currentContext;
- DebuggerAgent *m_agent;
QMutex m_lock;
QWaitCondition m_runningCondition;
State m_state;
@@ -214,54 +214,6 @@ private:
QWaitCondition m_jobIsRunning;
};
-class Q_QML_EXPORT DebuggerAgent : public QObject
-{
- Q_OBJECT
-public:
- DebuggerAgent(): m_breakOnThrow(false) {}
- ~DebuggerAgent();
-
- void addDebugger(Debugger *debugger);
- void removeDebugger(Debugger *debugger);
-
- void pause(Debugger *debugger) const;
- void pauseAll() const;
- void resumeAll() const;
- int addBreakPoint(const QString &fileName, int lineNumber, bool enabled = true, const QString &condition = QString());
- void removeBreakPoint(int id);
- void removeAllBreakPoints();
- void enableBreakPoint(int id, bool onoff);
- QList<int> breakPointIds(const QString &fileName, int lineNumber) const;
-
- bool breakOnThrow() const { return m_breakOnThrow; }
- void setBreakOnThrow(bool onoff);
-
- Q_INVOKABLE virtual void debuggerPaused(QV4::Debugging::Debugger *debugger,
- QV4::Debugging::PauseReason reason) = 0;
- Q_INVOKABLE virtual void sourcesCollected(QV4::Debugging::Debugger *debugger,
- QStringList sources, int requestSequenceNr) = 0;
-
-protected:
- QList<Debugger *> m_debuggers;
-
- struct BreakPoint {
- QString fileName;
- int lineNr;
- bool enabled;
- QString condition;
-
- BreakPoint(): lineNr(-1), enabled(false) {}
- BreakPoint(const QString &fileName, int lineNr, bool enabled, const QString &condition)
- : fileName(fileName), lineNr(lineNr), enabled(enabled), condition(condition)
- {}
-
- bool isValid() const { return lineNr >= 0 && !fileName.isEmpty(); }
- };
-
- QHash<int, BreakPoint> m_breakPoints;
- bool m_breakOnThrow;
-};
-
} // namespace Debugging
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index e1282eeca9..2560f065cf 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4context_p.h>
-#include <qv4value_inl_p.h>
+#include <qv4value_p.h>
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
@@ -48,7 +48,7 @@
#include <qv4regexp_p.h>
#include <qv4variantobject_p.h>
#include <qv4runtime_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include <qv4argumentsobject_p.h>
#include <qv4dateobject_p.h>
#include <qv4jsonobject_p.h>
@@ -59,7 +59,6 @@
#include "qv4executableallocator_p.h"
#include "qv4sequenceobject_p.h"
#include "qv4qobjectwrapper_p.h"
-#include "qv4qmlextensions_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraybuffer_p.h"
#include "qv4dataview_p.h"
@@ -197,9 +196,11 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: current(0)
+ , hasException(false)
, 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)
@@ -211,17 +212,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
- , m_qmlExtensions(0)
{
MemoryManager::GCBlocker gcBlocker(memoryManager);
- exceptionValue = Encode::undefined();
- hasException = false;
-
if (!factory) {
#ifdef V4_ENABLE_JIT
- static const bool forceMoth = !qgetenv("QV4_FORCE_INTERPRETER").isEmpty();
+ static const bool forceMoth = !qEnvironmentVariableIsEmpty("QV4_FORCE_INTERPRETER");
if (forceMoth)
factory = new Moth::ISelFactory;
else
@@ -241,6 +238,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
jsStackBase = (Value *)jsStack->base();
jsStackTop = jsStackBase;
+ exceptionValue = jsAlloca(1);
+ globalObject = static_cast<Object *>(jsAlloca(1));
+ jsObjects = jsAlloca(NJSObjects);
+ typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
+ typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
+ jsStrings = jsAlloca(NJSStrings);
+
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
#endif
@@ -251,208 +255,240 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
if (!recheckCStackLimits())
qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize);
- Scope scope(this);
-
identifierTable = new IdentifierTable(this);
classPool = new InternalClassPool;
emptyClass = new (classPool) InternalClass(this);
- id_empty = newIdentifier(QString());
- id_undefined = newIdentifier(QStringLiteral("undefined"));
- id_null = newIdentifier(QStringLiteral("null"));
- id_true = newIdentifier(QStringLiteral("true"));
- id_false = newIdentifier(QStringLiteral("false"));
- id_boolean = newIdentifier(QStringLiteral("boolean"));
- id_number = newIdentifier(QStringLiteral("number"));
- id_string = newIdentifier(QStringLiteral("string"));
- id_object = newIdentifier(QStringLiteral("object"));
- id_function = newIdentifier(QStringLiteral("function"));
- id_length = newIdentifier(QStringLiteral("length"));
- id_prototype = newIdentifier(QStringLiteral("prototype"));
- id_constructor = newIdentifier(QStringLiteral("constructor"));
- id_arguments = newIdentifier(QStringLiteral("arguments"));
- id_caller = newIdentifier(QStringLiteral("caller"));
- id_callee = newIdentifier(QStringLiteral("callee"));
- id_this = newIdentifier(QStringLiteral("this"));
- id___proto__ = newIdentifier(QStringLiteral("__proto__"));
- id_enumerable = newIdentifier(QStringLiteral("enumerable"));
- id_configurable = newIdentifier(QStringLiteral("configurable"));
- id_writable = newIdentifier(QStringLiteral("writable"));
- id_value = newIdentifier(QStringLiteral("value"));
- id_get = newIdentifier(QStringLiteral("get"));
- id_set = newIdentifier(QStringLiteral("set"));
- id_eval = newIdentifier(QStringLiteral("eval"));
- id_uintMax = newIdentifier(QStringLiteral("4294967295"));
- id_name = newIdentifier(QStringLiteral("name"));
- id_index = newIdentifier(QStringLiteral("index"));
- id_input = newIdentifier(QStringLiteral("input"));
- id_toString = newIdentifier(QStringLiteral("toString"));
- id_destroy = newIdentifier(QStringLiteral("destroy"));
- id_valueOf = newIdentifier(QStringLiteral("valueOf"));
- id_byteLength = newIdentifier(QStringLiteral("byteLength"));
- id_byteOffset = newIdentifier(QStringLiteral("byteOffset"));
- id_buffer = newIdentifier(QStringLiteral("buffer"));
- id_lastIndex = newIdentifier(QStringLiteral("lastIndex"));
-
- objectPrototype = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0);
-
- arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
- arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject());
-
- InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable);
- argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
- strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-
- m_globalObject = newObject();
- Q_ASSERT(globalObject()->d()->vtable);
+ jsStrings[String_Empty] = newIdentifier(QString());
+ jsStrings[String_undefined] = newIdentifier(QStringLiteral("undefined"));
+ jsStrings[String_null] = newIdentifier(QStringLiteral("null"));
+ jsStrings[String_true] = newIdentifier(QStringLiteral("true"));
+ jsStrings[String_false] = newIdentifier(QStringLiteral("false"));
+ jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean"));
+ jsStrings[String_number] = newIdentifier(QStringLiteral("number"));
+ jsStrings[String_string] = newIdentifier(QStringLiteral("string"));
+ jsStrings[String_object] = newIdentifier(QStringLiteral("object"));
+ jsStrings[String_function] = newIdentifier(QStringLiteral("function"));
+ jsStrings[String_length] = newIdentifier(QStringLiteral("length"));
+ jsStrings[String_prototype] = newIdentifier(QStringLiteral("prototype"));
+ jsStrings[String_constructor] = newIdentifier(QStringLiteral("constructor"));
+ jsStrings[String_arguments] = newIdentifier(QStringLiteral("arguments"));
+ jsStrings[String_caller] = newIdentifier(QStringLiteral("caller"));
+ jsStrings[String_callee] = newIdentifier(QStringLiteral("callee"));
+ jsStrings[String_this] = newIdentifier(QStringLiteral("this"));
+ jsStrings[String___proto__] = newIdentifier(QStringLiteral("__proto__"));
+ jsStrings[String_enumerable] = newIdentifier(QStringLiteral("enumerable"));
+ jsStrings[String_configurable] = newIdentifier(QStringLiteral("configurable"));
+ jsStrings[String_writable] = newIdentifier(QStringLiteral("writable"));
+ jsStrings[String_value] = newIdentifier(QStringLiteral("value"));
+ jsStrings[String_get] = newIdentifier(QStringLiteral("get"));
+ jsStrings[String_set] = newIdentifier(QStringLiteral("set"));
+ jsStrings[String_eval] = newIdentifier(QStringLiteral("eval"));
+ jsStrings[String_uintMax] = newIdentifier(QStringLiteral("4294967295"));
+ jsStrings[String_name] = newIdentifier(QStringLiteral("name"));
+ jsStrings[String_index] = newIdentifier(QStringLiteral("index"));
+ jsStrings[String_input] = newIdentifier(QStringLiteral("input"));
+ jsStrings[String_toString] = newIdentifier(QStringLiteral("toString"));
+ jsStrings[String_destroy] = newIdentifier(QStringLiteral("destroy"));
+ jsStrings[String_valueOf] = newIdentifier(QStringLiteral("valueOf"));
+ jsStrings[String_byteLength] = newIdentifier(QStringLiteral("byteLength"));
+ jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
+ jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
+ jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
+
+ jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(emptyClass);
+
+ arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
+ jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(arrayClass, objectPrototype());
+
+ InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable);
+ argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable);
+ strictArgumentsObjectClass = argsClass->addMember(id_callee(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+
+ *static_cast<Value *>(globalObject) = newObject();
+ Q_ASSERT(globalObject->d()->vtable());
initRootContext();
- stringPrototype = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype.asObject());
- numberPrototype = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype.asObject());
- booleanPrototype = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype.asObject());
- datePrototype = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype.asObject());
+ 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);
+ InternalClass *functionProtoClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
- functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject());
- functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
+ 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);
+ simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name);
- simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index);
+ simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length);
- protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index);
+ protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- regExpPrototype = memoryManager->alloc<RegExpPrototype>(this);
- regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
+ 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);
+ regExpExecArrayClass = regExpExecArrayClass->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- errorPrototype = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype.asObject());
- evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype.asObject());
- rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype.asObject());
- referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype.asObject());
- syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype.asObject());
- typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype.asObject());
- uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype.asObject());
-
- variantPrototype = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype.asObject());
- Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()->d());
-
- sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject()));
-
- ScopedContext global(scope, rootContext());
- objectCtor = memoryManager->alloc<ObjectCtor>(global);
- stringCtor = memoryManager->alloc<StringCtor>(global);
- numberCtor = memoryManager->alloc<NumberCtor>(global);
- booleanCtor = memoryManager->alloc<BooleanCtor>(global);
- arrayCtor = memoryManager->alloc<ArrayCtor>(global);
- functionCtor = memoryManager->alloc<FunctionCtor>(global);
- dateCtor = memoryManager->alloc<DateCtor>(global);
- regExpCtor = memoryManager->alloc<RegExpCtor>(global);
- errorCtor = memoryManager->alloc<ErrorCtor>(global);
- evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(global);
- rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(global);
- referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(global);
- syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(global);
- typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(global);
- uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(global);
-
- static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject());
- static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject());
- static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject());
- static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject());
- static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject());
- static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject());
- static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject());
- static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject());
- static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject());
- static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject());
- static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject());
- static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject());
- static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject());
- static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject());
- static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject());
-
- static_cast<VariantPrototype *>(variantPrototype.asObject())->init();
- sequencePrototype.cast<SequencePrototype>()->init();
+ 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());
+
+ 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());
+ static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
+ static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
+ static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
+ static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
+ static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
+ static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor());
+ static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor());
+ static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor());
+ static_cast<RangeErrorPrototype *>(rangeErrorPrototype())->init(this, rangeErrorCtor());
+ static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype())->init(this, referenceErrorCtor());
+ static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
+ static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
+ static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
+
+ static_cast<VariantPrototype *>(variantPrototype())->init();
+ sequencePrototype()->cast<SequencePrototype>()->init();
// typed arrays
- arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(global);
- arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject());
+ jsObjects[ArrayBuffer_Ctor] = memoryManager->allocObject<ArrayBufferCtor>(global);
+ jsObjects[ArrayBufferProto] = memoryManager->allocObject<ArrayBufferPrototype>();
+ static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor());
- dataViewCtor = memoryManager->alloc<DataViewCtor>(global);
- dataViewPrototype = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype.asObject());
- static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject());
+ 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) {
- typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
- typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
- typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject()));
+ 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>()));
}
//
// set up the global object
//
- rootContext()->global = globalObject()->d();
- rootContext()->callData->thisObject = globalObject();
- Q_ASSERT(globalObject()->d()->vtable);
-
- globalObject()->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("String"), stringCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
-
- globalObject()->defineDefaultProperty(QStringLiteral("ArrayBuffer"), arrayBufferCtor);
- globalObject()->defineDefaultProperty(QStringLiteral("DataView"), dataViewCtor);
- ScopedString str(scope);
+ rootContext()->d()->global = globalObject->d();
+ rootContext()->d()->callData->thisObject = globalObject;
+ Q_ASSERT(globalObject->d()->vtable());
+
+ globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Date"), *dateCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RegExp"), *regExpCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("Error"), *errorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("EvalError"), *evalErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("RangeError"), *rangeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), *referenceErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), *syntaxErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
+
+ globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor());
for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- globalObject()->defineDefaultProperty((str = typedArrayCtors[i].asFunctionObject()->name())->toQString(), typedArrayCtors[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));
+ 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));
- evalFunction = memoryManager->alloc<EvalFunction>(global);
- globalObject()->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
+ jsObjects[Eval_Function] = memoryManager->allocObject<EvalFunction>(global);
+ globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction());
- globalObject()->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
- globalObject()->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
- globalObject()->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
+ globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
+ globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
ScopedString name(scope, newString(QStringLiteral("thrower")));
- thrower = BuiltinFunction::create(global, name, ::throwTypeError);
+ jsObjects[ThrowerObject] = BuiltinFunction::create(global, name, ::throwTypeError);
}
ExecutionEngine::~ExecutionEngine()
@@ -471,7 +507,6 @@ ExecutionEngine::~ExecutionEngine()
foreach (QV4::CompiledData::CompilationUnit *unit, remainingUnits)
unit->unlink();
- delete m_qmlExtensions;
emptyClass->destroy();
delete classPool;
delete bumperPointerAllocator;
@@ -483,11 +518,10 @@ ExecutionEngine::~ExecutionEngine()
delete [] argumentsAccessors;
}
-void ExecutionEngine::enableDebugger()
+void ExecutionEngine::setDebugger(Debugging::Debugger *debugger_)
{
Q_ASSERT(!debugger);
- debugger = new Debugging::Debugger(this);
- iselFactory.reset(new Moth::ISelFactory);
+ debugger = debugger_;
}
void ExecutionEngine::enableProfiler()
@@ -502,12 +536,15 @@ void ExecutionEngine::initRootContext()
Scoped<GlobalContext> r(scope, memoryManager->allocManaged<GlobalContext>(sizeof(GlobalContext::Data) + sizeof(CallData)));
new (r->d()) GlobalContext::Data(this);
r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
- r->d()->callData->tag = QV4::Value::_Integer_Type;
+ r->d()->callData->tag = QV4::Value::Integer_Type_Internal;
r->d()->callData->argc = 0;
- r->d()->callData->thisObject = globalObject();
+ r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
+ jsObjects[RootContext] = r;
+ jsObjects[IntegerNull] = Encode((int)0);
- m_rootContext = r->d();
+ currentContext = static_cast<ExecutionContext *>(jsObjects + RootContext);
+ current = currentContext->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -515,29 +552,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()->callData;
+ pushContext(rootContext()->d());
+
+ Q_ASSERT(current == rootContext()->d());
+ return currentContext;
+}
- Q_ASSERT(currentContext() == g->d());
- return g->d();
+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)
@@ -551,31 +590,25 @@ Heap::String *ExecutionEngine::newIdentifier(const QString &text)
return identifierTable->insertString(text);
}
-Heap::Object *ExecutionEngine::newStringObject(const Value &value)
+Heap::Object *ExecutionEngine::newStringObject(const String *string)
{
- Scope scope(this);
- Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value));
- 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)
@@ -585,39 +618,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();
}
@@ -638,97 +692,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.asObject(), 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::Object *ExecutionEngine::qmlContextObject() const
+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;
@@ -740,8 +772,46 @@ Heap::Object *ExecutionEngine::qmlContextObject() const
if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
return 0;
- Q_ASSERT(static_cast<Heap::CallContext *>(ctx)->activation);
- return static_cast<Heap::CallContext *>(ctx)->activation;
+ return static_cast<Heap::QmlContext *>(ctx);
+}
+
+QObject *ExecutionEngine::qmlScopeObject() const
+{
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
+
+ return ctx->qml->scopeObject;
+}
+
+ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
+{
+ QQmlContextData *ctx = callingQmlContext();
+ if (!ctx->imports)
+ return Encode::undefined();
+ // Search for attached properties, enums and imported scripts
+ QQmlTypeNameCache::Result r = ctx->imports->query(name);
+
+ Q_ASSERT(r.isValid());
+ Q_ASSERT(r.type);
+ Q_ASSERT(r.type->isSingleton());
+
+ QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
+ QQmlEngine *e = qmlEngine();
+ siinfo->init(e);
+
+ if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
+ return QV4::QObjectWrapper::wrap(this, qobjectSingleton);
+ return QJSValuePrivate::convertedToValue(this, siinfo->scriptApi(e));
+}
+
+QQmlContextData *ExecutionEngine::callingQmlContext() const
+{
+ Heap::QmlContext *ctx = qmlContext();
+ if (!ctx)
+ return 0;
+
+ return ctx->qml->context.contextData();
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -750,7 +820,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();
@@ -770,14 +840,14 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
stack.append(frame);
--frameLimit;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (frameLimit && globalCode) {
StackFrame frame;
frame.source = globalCode->sourceFile();
frame.function = globalCode->name()->toQString();
- frame.line = rootContext()->lineNumber;
+ frame.line = rootContext()->d()->lineNumber;
frame.column = -1;
stack.append(frame);
@@ -838,8 +908,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) {
@@ -847,7 +916,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)
@@ -877,10 +946,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));
}
}
}
@@ -889,8 +958,6 @@ void ExecutionEngine::markObjects()
{
identifierTable->mark(this);
- globalObject()->mark(this);
-
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
if (Heap::FunctionObject *getter = pd.getter())
@@ -899,103 +966,6 @@ void ExecutionEngine::markObjects()
setter->mark(this);
}
- Heap::ExecutionContext *c = currentContext();
- while (c) {
- Q_ASSERT(c->inUse());
- if (!c->isMarked()) {
- c->setMarkBit();
- c->gcGetVtable()->markObjects(c, this);
- }
- c = c->parent;
- }
-
- id_empty->mark(this);
- id_undefined->mark(this);
- id_null->mark(this);
- id_true->mark(this);
- id_false->mark(this);
- id_boolean->mark(this);
- id_number->mark(this);
- id_string->mark(this);
- id_object->mark(this);
- id_function->mark(this);
- id_length->mark(this);
- id_prototype->mark(this);
- id_constructor->mark(this);
- id_arguments->mark(this);
- id_caller->mark(this);
- id_callee->mark(this);
- id_this->mark(this);
- id___proto__->mark(this);
- id_enumerable->mark(this);
- id_configurable->mark(this);
- id_writable->mark(this);
- id_value->mark(this);
- id_get->mark(this);
- id_set->mark(this);
- id_eval->mark(this);
- id_uintMax->mark(this);
- id_name->mark(this);
- id_index->mark(this);
- id_input->mark(this);
- id_toString->mark(this);
- id_destroy->mark(this);
- id_valueOf->mark(this);
- id_byteLength->mark(this);
- id_byteOffset->mark(this);
- id_buffer->mark(this);
- id_lastIndex->mark(this);
-
- objectCtor.mark(this);
- stringCtor.mark(this);
- numberCtor.mark(this);
- booleanCtor.mark(this);
- arrayCtor.mark(this);
- functionCtor.mark(this);
- dateCtor.mark(this);
- regExpCtor.mark(this);
- errorCtor.mark(this);
- evalErrorCtor.mark(this);
- rangeErrorCtor.mark(this);
- referenceErrorCtor.mark(this);
- syntaxErrorCtor.mark(this);
- typeErrorCtor.mark(this);
- uRIErrorCtor.mark(this);
- arrayBufferCtor.mark(this);
- dataViewCtor.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayCtors[i].mark(this);
-
- objectPrototype.mark(this);
- arrayPrototype.mark(this);
- stringPrototype.mark(this);
- numberPrototype.mark(this);
- booleanPrototype.mark(this);
- datePrototype.mark(this);
- functionPrototype.mark(this);
- regExpPrototype.mark(this);
- errorPrototype.mark(this);
- evalErrorPrototype.mark(this);
- rangeErrorPrototype.mark(this);
- referenceErrorPrototype.mark(this);
- syntaxErrorPrototype.mark(this);
- typeErrorPrototype.mark(this);
- uRIErrorPrototype.mark(this);
- variantPrototype.mark(this);
- sequencePrototype.mark(this);
-
- arrayBufferPrototype.mark(this);
- dataViewPrototype.mark(this);
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- typedArrayPrototype[i].mark(this);
-
- exceptionValue.mark(this);
-
- thrower->mark(this);
-
- if (m_qmlExtensions)
- m_qmlExtensions->markObjects(this);
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
@@ -1003,13 +973,6 @@ void ExecutionEngine::markObjects()
(*it)->markObjects(this);
}
-QmlExtensions *ExecutionEngine::qmlExtensions()
-{
- if (!m_qmlExtensions)
- m_qmlExtensions = new QmlExtensions;
- return m_qmlExtensions;
-}
-
ReturnedValue ExecutionEngine::throwError(const Value &value)
{
// we can get in here with an exception already set, as the runtime
@@ -1020,7 +983,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
return Encode::undefined();
hasException = true;
- exceptionValue = value;
+ *exceptionValue = value;
QV4::Scope scope(this);
QV4::Scoped<ErrorObject> error(scope, value);
if (!!error)
@@ -1041,8 +1004,8 @@ ReturnedValue ExecutionEngine::catchException(StackTrace *trace)
*trace = exceptionStackTrace;
exceptionStackTrace.clear();
hasException = false;
- ReturnedValue res = exceptionValue.asReturnedValue();
- exceptionValue = Primitive::emptyValue();
+ ReturnedValue res = exceptionValue->asReturnedValue();
+ *exceptionValue = Primitive::emptyValue();
return res;
}
@@ -1139,7 +1102,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
QV4::ScopedValue exception(scope, catchException(&trace));
QQmlError error;
if (!trace.isEmpty()) {
- QV4::StackFrame frame = trace.first();
+ QV4::StackFrame frame = trace.constFirst();
error.setUrl(QUrl(frame.source));
error.setLine(frame.line);
error.setColumn(frame.column);
@@ -1175,7 +1138,7 @@ bool ExecutionEngine::recheckCStackLimits()
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value);
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects = 0);
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = 0);
static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
const QByteArray &targetType,
void **result);
@@ -1198,7 +1161,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
Q_ASSERT (!value.isEmpty());
QV4::Scope scope(e);
- if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
+ if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
return v->d()->data;
if (typeHint == QVariant::Bool)
@@ -1210,10 +1173,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (typeHint == qMetaTypeId<QJSValue>())
return QVariant::fromValue(QJSValue(e, value.asReturnedValue()));
- if (value.asObject()) {
+ if (value.as<Object>()) {
QV4::ScopedObject object(scope, value);
if (typeHint == QMetaType::QJsonObject
- && !value.asArrayObject() && !value.asFunctionObject()) {
+ && !value.as<ArrayObject>() && !value.as<FunctionObject>()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
return qVariantFromValue<QObject *>(wrapper->object());
@@ -1229,7 +1192,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QV4::SequencePrototype::toVariant(object);
}
- if (value.asArrayObject()) {
+ if (value.as<ArrayObject>()) {
QV4::ScopedArrayObject a(scope, value);
if (typeHint == qMetaTypeId<QList<QObject *> >()) {
QList<QObject *> list;
@@ -1267,11 +1230,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return value.asDouble();
if (value.isString())
return value.stringValue()->toQString();
- if (QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
+ if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
return ld->d()->locale;
- if (QV4::DateObject *d = value.asDateObject())
+ if (const QV4::DateObject *d = value.as<DateObject>())
return d->toQDateTime();
- if (QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
+ if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>())
return d->asByteArray();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -1287,7 +1250,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return objectToVariant(e, o, visitedObjects);
}
-static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects)
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects)
{
Q_ASSERT(o);
@@ -1298,7 +1261,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
- if (o->asArrayObject())
+ if (o->as<ArrayObject>())
return QVariantList();
return QVariantMap();
}
@@ -1306,7 +1269,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
QVariant result;
- if (o->asArrayObject()) {
+ if (o->as<ArrayObject>()) {
QV4::Scope scope(e);
QV4::ScopedArrayObject a(scope, o->asReturnedValue());
QV4::ScopedValue v(scope);
@@ -1319,7 +1282,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec
}
result = list;
- } else if (!o->asFunctionObject()) {
+ } else if (!o->as<FunctionObject>()) {
QVariantMap map;
QV4::Scope scope(e);
QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
@@ -1497,7 +1460,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newVariantObject(variant));
}
-QVariantMap ExecutionEngine::variantMapFromJS(Object *o)
+QVariantMap ExecutionEngine::variantMapFromJS(const Object *o)
{
return objectToVariant(this, o).toMap();
}
@@ -1630,93 +1593,90 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-void ExecutionEngine::assertObjectBelongsToEngine(const Value &v)
+void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject)
{
- Q_UNUSED(v);
- Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this);
- Q_UNUSED(v);
+ Q_ASSERT(!baseObject.vtable()->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this);
+ Q_UNUSED(baseObject);
}
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
-bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *data)
+bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
{
- QV4::Scope scope(this);
-
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
case QMetaType::Bool:
- *reinterpret_cast<bool*>(data) = value.toBoolean();
+ *reinterpret_cast<bool*>(data) = value->toBoolean();
return true;
case QMetaType::Int:
- *reinterpret_cast<int*>(data) = value.toInt32();
+ *reinterpret_cast<int*>(data) = value->toInt32();
return true;
case QMetaType::UInt:
- *reinterpret_cast<uint*>(data) = value.toUInt32();
+ *reinterpret_cast<uint*>(data) = value->toUInt32();
return true;
case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
return true;
case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
return true;
case QMetaType::Double:
- *reinterpret_cast<double*>(data) = value.toNumber();
+ *reinterpret_cast<double*>(data) = value->toNumber();
return true;
case QMetaType::QString:
- if (value.isUndefined() || value.isNull())
+ if (value->isUndefined() || value->isNull())
*reinterpret_cast<QString*>(data) = QString();
else
- *reinterpret_cast<QString*>(data) = value.toQString();
+ *reinterpret_cast<QString*>(data) = value->toQString();
return true;
case QMetaType::Float:
- *reinterpret_cast<float*>(data) = value.toNumber();
+ *reinterpret_cast<float*>(data) = value->toNumber();
return true;
case QMetaType::Short:
- *reinterpret_cast<short*>(data) = short(value.toInt32());
+ *reinterpret_cast<short*>(data) = short(value->toInt32());
return true;
case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
+ *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
return true;
case QMetaType::Char:
- *reinterpret_cast<char*>(data) = char(value.toInt32());
+ *reinterpret_cast<char*>(data) = char(value->toInt32());
return true;
case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
return true;
case QMetaType::QChar:
- if (value.isString()) {
- QString str = value.stringValue()->toQString();
+ if (value->isString()) {
+ QString str = value->stringValue()->toQString();
*reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
} else {
- *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
}
return true;
case QMetaType::QDateTime:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
return true;
} break;
case QMetaType::QDate:
- if (QV4::DateObject *d = value.asDateObject()) {
+ if (const QV4::DateObject *d = value->as<DateObject>()) {
*reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
return true;
} break;
case QMetaType::QRegExp:
- if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
+ if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
case QMetaType::QObjectStar: {
- QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
- if (qobjectWrapper || value.isNull()) {
- *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value);
+ const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
+ if (qobjectWrapper || value->isNull()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(this, *value);
return true;
} break;
}
case QMetaType::QStringList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
*reinterpret_cast<QStringList *>(data) = a->toQStringList();
return true;
@@ -1724,15 +1684,15 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariantList: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
if (a) {
- *reinterpret_cast<QVariantList *>(data) = scope.engine->toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ *reinterpret_cast<QVariantList *>(data) = toVariant(*a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
return true;
}
break;
}
case QMetaType::QVariantMap: {
- QV4::ScopedObject o(scope, value);
+ const QV4::Object *o = value->as<QV4::Object>();
if (o) {
*reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
return true;
@@ -1740,20 +1700,19 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
break;
}
case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = scope.engine->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ *reinterpret_cast<QVariant*>(data) = toVariant(*value, /*typeHint*/-1, /*createJSValueForObjects*/false);
return true;
case QMetaType::QJsonValue:
- *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
+ *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(*value);
return true;
case QMetaType::QJsonObject: {
- QV4::ScopedObject o(scope, value);
- *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(o);
+ *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value->as<Object>());
return true;
}
case QMetaType::QJsonArray: {
- QV4::ScopedArrayObject a(scope, value);
+ const QV4::ArrayObject *a = value->as<ArrayObject>();
if (a) {
- *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(a);
+ *reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
return true;
}
break;
@@ -1763,7 +1722,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
{
- QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value);
+ const QQmlValueTypeWrapper *vtw = value->as<QQmlValueTypeWrapper>();
if (vtw && vtw->typeId() == type) {
return vtw->toGadget(data);
}
@@ -1788,21 +1747,22 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
}
#endif
- // Try to use magic; for compatibility with qscriptvalue_cast.
+ // Try to use magic; for compatibility with qjsvalue_cast.
QByteArray name = QMetaType::typeName(type);
- if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data)))
+ if (convertToNativeQObject(this, *value, name, reinterpret_cast<void* *>(data)))
return true;
- if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
+ if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value.as<QV4::VariantObject>()->d()->data;
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
- } else if (value.isObject()) {
+ } else if (value->isObject()) {
// Look in the prototype chain.
- QV4::ScopedObject proto(scope, value.objectValue()->prototype());
+ QV4::Scope scope(this);
+ QV4::ScopedObject proto(scope, value->objectValue()->prototype());
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -1812,7 +1772,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(scope.engine, p))
+ if (QObject *qobject = qtObjectFromJS(this, p))
canCast = qobject->qt_metacast(className) != 0;
}
if (canCast) {
@@ -1826,11 +1786,11 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
proto = proto->prototype();
}
}
- } else if (value.isNull() && name.endsWith('*')) {
+ } else if (value->isNull() && name.endsWith('*')) {
*reinterpret_cast<void* *>(data) = 0;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
- *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value.asReturnedValue());
+ *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value->asReturnedValue());
return true;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index c0c88abaa5..4640f3f4cc 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -33,10 +33,22 @@
#ifndef QV4ENGINE_H
#define QV4ENGINE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "private/qv4isel_p.h"
#include "qv4managed_p.h"
#include "qv4context_p.h"
+#include "qv4internalclass_p.h"
#include <private/qintrusivelist_p.h>
namespace WTF {
@@ -50,6 +62,7 @@ class QV8Engine;
class QQmlError;
class QJSEngine;
class QQmlEngine;
+class QQmlContextData;
namespace QV4 {
namespace Debugging {
@@ -76,18 +89,16 @@ private:
friend struct Heap::ExecutionContext;
public:
Heap::ExecutionContext *current;
- Heap::ExecutionContext *currentContext() const { return current; }
Value *jsStackTop;
quint32 hasException;
- Heap::GlobalContext *m_rootContext;
- Heap::GlobalContext *rootContext() const { return m_rootContext; }
MemoryManager *memoryManager;
ExecutableAllocator *executableAllocator;
ExecutableAllocator *regExpAllocator;
QScopedPointer<EvalISelFactory> iselFactory;
+ ExecutionContext *currentContext;
Value *jsStackLimit;
quintptr cStackLimit;
@@ -106,14 +117,19 @@ public:
--jsStackTop;
return jsStackTop->heapObject();
}
+ Value *jsAlloca(int nValues) {
+ Value *ptr = jsStackTop;
+ jsStackTop = ptr + nValues;
+ memset(ptr, 0, nValues*sizeof(Value));
+ return ptr;
+ }
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
- Value m_globalObject;
- Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); }
+ Object *globalObject;
Function *globalCode;
@@ -121,104 +137,206 @@ public:
QQmlEngine *qmlEngine() const;
QV8Engine *v8Engine;
- Value objectCtor;
- Value stringCtor;
- Value numberCtor;
- Value booleanCtor;
- Value arrayCtor;
- Value functionCtor;
- Value dateCtor;
- Value regExpCtor;
- Value errorCtor;
- Value evalErrorCtor;
- Value rangeErrorCtor;
- Value referenceErrorCtor;
- Value syntaxErrorCtor;
- Value typeErrorCtor;
- Value uRIErrorCtor;
- Value arrayBufferCtor;
- Value dataViewCtor;
- enum { NTypedArrayTypes = 9 }; // avoid header dependency
- Value typedArrayCtors[NTypedArrayTypes];
-
- Value objectPrototype;
- Value arrayPrototype;
- Value stringPrototype;
- Value numberPrototype;
- Value booleanPrototype;
- Value datePrototype;
- Value functionPrototype;
- Value regExpPrototype;
- Value errorPrototype;
- Value evalErrorPrototype;
- Value rangeErrorPrototype;
- Value referenceErrorPrototype;
- Value syntaxErrorPrototype;
- Value typeErrorPrototype;
- Value uRIErrorPrototype;
- Value variantPrototype;
- Value sequencePrototype;
-
- Value arrayBufferPrototype;
- Value dataViewPrototype;
- Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here
+ enum JSObjects {
+ RootContext,
+ IntegerNull, // Has to come after the RootContext to make the context stack safe
+ ObjectProto,
+ ArrayProto,
+ StringProto,
+ NumberProto,
+ BooleanProto,
+ DateProto,
+ FunctionProto,
+ RegExpProto,
+ ErrorProto,
+ EvalErrorProto,
+ RangeErrorProto,
+ ReferenceErrorProto,
+ SyntaxErrorProto,
+ TypeErrorProto,
+ URIErrorProto,
+ VariantProto,
+ SequenceProto,
+ ArrayBufferProto,
+ DataViewProto,
+ ValueTypeProto,
+ SignalHandlerProto,
+
+ Object_Ctor,
+ String_Ctor,
+ Number_Ctor,
+ Boolean_Ctor,
+ Array_Ctor,
+ Function_Ctor,
+ Date_Ctor,
+ RegExp_Ctor,
+ Error_Ctor,
+ EvalError_Ctor,
+ RangeError_Ctor,
+ ReferenceError_Ctor,
+ SyntaxError_Ctor,
+ TypeError_Ctor,
+ URIError_Ctor,
+ ArrayBuffer_Ctor,
+ DataView_Ctor,
+
+ Eval_Function,
+ GetStack_Function,
+ ThrowerObject,
+ NJSObjects
+ };
+ Value *jsObjects;
+ enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency
+
+ 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); }
+ FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); }
+ FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); }
+ FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); }
+ FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); }
+ FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); }
+ FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); }
+ FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); }
+ FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); }
+ FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); }
+ FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); }
+ FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); }
+ FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); }
+ FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); }
+ FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); }
+ FunctionObject *typedArrayCtors;
+
+ Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); }
+ Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); }
+ Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); }
+ Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); }
+ Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); }
+ Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); }
+ Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); }
+ Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); }
+ Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); }
+ Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); }
+ Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); }
+ Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); }
+ Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); }
+ Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); }
+ Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); }
+ Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); }
+ Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); }
+
+ Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); }
+ Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); }
+ 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;
- Heap::EvalFunction *evalFunction;
- Heap::FunctionObject *thrower;
+ 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;
int nArgumentsAccessors;
- StringValue id_empty;
- StringValue id_undefined;
- StringValue id_null;
- StringValue id_true;
- StringValue id_false;
- StringValue id_boolean;
- StringValue id_number;
- StringValue id_string;
- StringValue id_object;
- StringValue id_function;
- StringValue id_length;
- StringValue id_prototype;
- StringValue id_constructor;
- StringValue id_arguments;
- StringValue id_caller;
- StringValue id_callee;
- StringValue id_this;
- StringValue id___proto__;
- StringValue id_enumerable;
- StringValue id_configurable;
- StringValue id_writable;
- StringValue id_value;
- StringValue id_get;
- StringValue id_set;
- StringValue id_eval;
- StringValue id_uintMax;
- StringValue id_name;
- StringValue id_index;
- StringValue id_input;
- StringValue id_toString;
- StringValue id_destroy;
- StringValue id_valueOf;
- StringValue id_byteLength;
- StringValue id_byteOffset;
- StringValue id_buffer;
- StringValue id_lastIndex;
+ enum JSStrings {
+ String_Empty,
+ String_undefined,
+ String_null,
+ String_true,
+ String_false,
+ String_boolean,
+ String_number,
+ String_string,
+ String_object,
+ String_function,
+ String_length,
+ String_prototype,
+ String_constructor,
+ String_arguments,
+ String_caller,
+ String_callee,
+ String_this,
+ String___proto__,
+ String_enumerable,
+ String_configurable,
+ String_writable,
+ String_value,
+ String_get,
+ String_set,
+ String_eval,
+ String_uintMax,
+ String_name,
+ String_index,
+ String_input,
+ String_toString,
+ String_destroy,
+ String_valueOf,
+ String_byteLength,
+ String_byteOffset,
+ String_buffer,
+ String_lastIndex,
+ NJSStrings
+ };
+ Value *jsStrings;
+
+ String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
+ String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
+ String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
+ String *id_true() const { return reinterpret_cast<String *>(jsStrings + String_true); }
+ String *id_false() const { return reinterpret_cast<String *>(jsStrings + String_false); }
+ String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); }
+ String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); }
+ String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); }
+ String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); }
+ String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); }
+ String *id_length() const { return reinterpret_cast<String *>(jsStrings + String_length); }
+ String *id_prototype() const { return reinterpret_cast<String *>(jsStrings + String_prototype); }
+ String *id_constructor() const { return reinterpret_cast<String *>(jsStrings + String_constructor); }
+ String *id_arguments() const { return reinterpret_cast<String *>(jsStrings + String_arguments); }
+ String *id_caller() const { return reinterpret_cast<String *>(jsStrings + String_caller); }
+ String *id_callee() const { return reinterpret_cast<String *>(jsStrings + String_callee); }
+ String *id_this() const { return reinterpret_cast<String *>(jsStrings + String_this); }
+ String *id___proto__() const { return reinterpret_cast<String *>(jsStrings + String___proto__); }
+ String *id_enumerable() const { return reinterpret_cast<String *>(jsStrings + String_enumerable); }
+ String *id_configurable() const { return reinterpret_cast<String *>(jsStrings + String_configurable); }
+ String *id_writable() const { return reinterpret_cast<String *>(jsStrings + String_writable); }
+ String *id_value() const { return reinterpret_cast<String *>(jsStrings + String_value); }
+ String *id_get() const { return reinterpret_cast<String *>(jsStrings + String_get); }
+ String *id_set() const { return reinterpret_cast<String *>(jsStrings + String_set); }
+ String *id_eval() const { return reinterpret_cast<String *>(jsStrings + String_eval); }
+ String *id_uintMax() const { return reinterpret_cast<String *>(jsStrings + String_uintMax); }
+ String *id_name() const { return reinterpret_cast<String *>(jsStrings + String_name); }
+ String *id_index() const { return reinterpret_cast<String *>(jsStrings + String_index); }
+ String *id_input() const { return reinterpret_cast<String *>(jsStrings + String_input); }
+ String *id_toString() const { return reinterpret_cast<String *>(jsStrings + String_toString); }
+ String *id_destroy() const { return reinterpret_cast<String *>(jsStrings + String_destroy); }
+ String *id_valueOf() const { return reinterpret_cast<String *>(jsStrings + String_valueOf); }
+ String *id_byteLength() const { return reinterpret_cast<String *>(jsStrings + String_byteLength); }
+ String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
+ String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
+ String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
QSet<CompiledData::CompilationUnit*> compilationUnits;
@@ -248,12 +366,14 @@ public:
ExecutionEngine(EvalISelFactory *iselFactory = 0);
~ExecutionEngine();
- void enableDebugger();
+ void setDebugger(Debugging::Debugger *debugger);
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);
@@ -261,15 +381,17 @@ public:
Heap::String *newString(const QString &s = QString());
Heap::String *newIdentifier(const QString &text);
- Heap::Object *newStringObject(const Value &value);
+ Heap::Object *newStringObject(const String *string);
Heap::Object *newNumberObject(double value);
Heap::Object *newBooleanObject(bool b);
Heap::ArrayObject *newArrayObject(int count = 0);
+ Heap::ArrayObject *newArrayObject(const Value *values, int length);
Heap::ArrayObject *newArrayObject(const QStringList &list);
Heap::ArrayObject *newArrayObject(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);
@@ -282,7 +404,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);
@@ -291,7 +413,11 @@ public:
Heap::Object *newForEachIteratorObject(Object *o);
- Heap::Object *qmlContextObject() const;
+ Heap::QmlContext *qmlContext() const;
+ QObject *qmlScopeObject() const;
+ ReturnedValue qmlSingletonWrapper(String *name);
+ QQmlContextData *callingQmlContext() const;
+
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
@@ -305,12 +431,10 @@ public:
InternalClass *newClass(const InternalClass &other);
- QmlExtensions *qmlExtensions();
-
bool recheckCStackLimits();
// Exception handling
- Value exceptionValue;
+ Value *exceptionValue;
StackTrace exceptionStackTrace;
ReturnedValue throwError(const Value &value);
@@ -335,70 +459,62 @@ public:
QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
QV4::ReturnedValue fromVariant(const QVariant &);
- QVariantMap variantMapFromJS(QV4::Object *o);
+ QVariantMap variantMapFromJS(const QV4::Object *o);
- bool metaTypeFromJS(const Value &value, int type, void *data);
+ bool metaTypeFromJS(const Value *value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
- void assertObjectBelongsToEngine(const Value &v);
-
-private:
- QmlExtensions *m_qmlExtensions;
+ 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();
}
-
-// ### Remove me
inline
-void Managed::mark(QV4::ExecutionEngine *engine)
+void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
- if (markBit())
+ if (isMarked())
return;
#ifndef QT_NO_DEBUG
engine->assertObjectBelongsToEngine(*this);
#endif
- d()->setMarkBit();
- engine->pushForGC(d());
+ setMarkBit();
+ engine->pushForGC(this);
}
-
-inline
-void Heap::Base::mark(QV4::ExecutionEngine *engine)
+inline void Value::mark(ExecutionEngine *e)
{
- Q_ASSERT(inUse());
- if (isMarked())
+ if (!isManaged())
return;
- setMarkBit();
- engine->pushForGC(this);
+
+ Heap::Base *o = heapObject();
+ if (o)
+ o->mark(e);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 9034dee6a0..87b7a88a2b 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -33,11 +33,14 @@
#include "qv4errorobject_p.h"
-#include "qv4mm_p.h"
+#include <QtCore/qnumeric.h>
+#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
+#include "qv4string_p.h"
+#include <private/qv4mm_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
@@ -58,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;
@@ -133,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)
@@ -178,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.asObject(), msg, SyntaxError)
-{
-}
-
-Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError)
-{
-}
-
-Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype.asObject(), message, EvalError)
-{
-}
-
-Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
- : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), 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.asObject(), 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.asObject(), 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.asObject(), 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.asObject(), 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.asObject(), 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.asObject(), 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.asObject(), message, URIError)
+Heap::URIErrorObject::URIErrorObject(const Value &message)
+ : Heap::ErrorObject(message, URIError)
{
}
@@ -251,16 +237,16 @@ Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name)
{
}
-ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ErrorCtor *>(m)->engine());
+ 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(Managed *that, CallData *callData)
+ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData)
{
- return static_cast<Object *>(that)->construct(callData);
+ return static_cast<const Object *>(that)->construct(callData);
}
Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
@@ -268,11 +254,11 @@ Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<EvalErrorCtor *>(m)->engine());
+ 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)
@@ -280,11 +266,11 @@ Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<RangeErrorCtor *>(m)->engine());
+ 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)
@@ -292,11 +278,11 @@ Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<ReferenceErrorCtor *>(m)->engine());
+ 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)
@@ -304,11 +290,11 @@ Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<SyntaxErrorCtor *>(m)->engine());
+ 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)
@@ -316,11 +302,11 @@ Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<TypeErrorCtor *>(m)->engine());
+ 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)
@@ -328,41 +314,43 @@ Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<URIErrorCtor *>(m)->engine());
+ 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()));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ *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)
{
Scope scope(ctx);
- Object *o = ctx->thisObject().asObject();
+ Object *o = ctx->thisObject().as<Object>();
if (!o)
return ctx->engine()->throwTypeError();
- ScopedValue name(scope, o->get(ctx->d()->engine->id_name));
+ ScopedValue name(scope, o->get(ctx->d()->engine->id_name()));
QString qname;
if (name->isUndefined())
- qname = QString::fromLatin1("Error");
+ qname = QStringLiteral("Error");
else
qname = name->toQString();
- ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message")));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("message")));
ScopedValue message(scope, o->get(s));
QString qmessage;
if (!message->isUndefined())
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 071f5b8c9a..336050ab2b 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -33,8 +33,20 @@
#ifndef QV4ERROROBJECT_H
#define QV4ERROROBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -55,43 +67,39 @@ 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;
- String *stack;
+ Pointer<String> stack;
};
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,51 +138,75 @@ 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);
};
template<>
-inline ErrorObject *value_cast(const Value &v) {
- return v.asErrorObject();
+inline const ErrorObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : 0;
}
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()); }
};
@@ -183,89 +215,94 @@ struct ErrorCtor: FunctionObject
{
V4_OBJECT2(ErrorCtor, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct EvalErrorCtor: ErrorCtor
{
V4_OBJECT2(EvalErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
V4_OBJECT2(RangeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
V4_OBJECT2(ReferenceErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
V4_OBJECT2(SyntaxErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
V4_OBJECT2(TypeErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
V4_OBJECT2(URIErrorCtor, ErrorCtor)
- static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
};
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 +311,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/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h
index 0d07e3c1bd..bb63d423a6 100644
--- a/src/qml/jsruntime/qv4executableallocator_p.h
+++ b/src/qml/jsruntime/qv4executableallocator_p.h
@@ -34,6 +34,17 @@
#ifndef QV4EXECUTABLEALLOCATOR_H
#define QV4EXECUTABLEALLOCATOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include <QMultiMap>
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index be63b31e1e..66b2125a4f 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -34,10 +34,10 @@
#include "qv4function_p.h"
#include "qv4managed_p.h"
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4engine_p.h"
#include "qv4lookup_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
@@ -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..0e1216a45b 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -33,6 +33,17 @@
#ifndef QV4FUNCTION_H
#define QV4FUNCTION_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include <private/qv4compileddata_p.h>
@@ -49,11 +60,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 +80,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 0a12d013ac..1194033872 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4function_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4arrayobject_p.h"
#include "qv4scopedvalue_p.h"
@@ -46,7 +46,7 @@
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
-#include <private/qqmlcontextwrapper_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmlengine_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
@@ -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.asObject())
- , 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.asObject())
- , 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.asObject())
- , 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.asObject())
- , 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.asObject())
- , 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.asObject())
- , 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())
+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,23 +141,23 @@ 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.asObject()));
- 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();
+ ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
+ 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);
- defineReadonlyProperty(s.engine->id_name, v);
+ defineReadonlyProperty(s.engine->id_name(), v);
}
-ReturnedValue FunctionObject::name()
+ReturnedValue FunctionObject::name() const
{
- return get(scope()->engine->id_name);
+ return get(scope()->engine->id_name());
}
@@ -177,13 +168,12 @@ ReturnedValue FunctionObject::newInstance()
return construct(callData);
}
-ReturnedValue FunctionObject::construct(Managed *that, CallData *)
+ReturnedValue FunctionObject::construct(const Managed *that, CallData *)
{
- static_cast<FunctionObject *>(that)->internalClass()->engine->throwTypeError();
- return Encode::undefined();
+ return static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
}
-ReturnedValue FunctionObject::call(Managed *, CallData *)
+ReturnedValue FunctionObject::call(const Managed *, CallData *)
{
return Encode::undefined();
}
@@ -203,18 +193,36 @@ 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();
+ return d()->vtable() == QQmlBindingFunction::staticVTable();
}
bool FunctionObject::isBoundFunction() const
{
- return d()->vtable == BoundFunction::staticVTable();
+ return d()->vtable() == BoundFunction::staticVTable();
}
QQmlSourceLocation FunctionObject::sourceLocation() const
@@ -237,11 +245,11 @@ Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
}
// 15.3.2
-ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData)
{
- Scope scope(static_cast<Object *>(that)->engine());
- Scoped<FunctionCtor> f(scope, static_cast<FunctionCtor *>(that));
- ScopedContext ctx(scope, scope.engine->currentContext());
+ Scope scope(static_cast<const Object *>(that)->engine());
+ Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that));
+
QString arguments;
QString body;
if (callData->argc > 0) {
@@ -252,10 +260,10 @@ ReturnedValue FunctionCtor::construct(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("}");
+ QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1Char('}');
QQmlJS::Engine ee, *engine = &ee;
QQmlJS::Lexer lexer(engine);
@@ -282,20 +290,19 @@ ReturnedValue FunctionCtor::construct(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();
}
// 15.3.1: This is equivalent to new Function(...)
-ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData)
{
return construct(that, callData);
}
DEFINE_OBJECT_VTABLE(FunctionPrototype);
-Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype)
- : Heap::FunctionObject(ic, prototype)
+Heap::FunctionPrototype::FunctionPrototype()
{
}
@@ -304,12 +311,12 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
- defineReadonlyProperty(engine->id_length, Primitive::fromInt32(0));
+ defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("apply"), method_apply, 2);
defineDefaultProperty(QStringLiteral("call"), method_call, 1);
defineDefaultProperty(QStringLiteral("bind"), method_bind, 1);
@@ -318,7 +325,7 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
{
- FunctionObject *fun = ctx->thisObject().asFunctionObject();
+ FunctionObject *fun = ctx->thisObject().as<FunctionObject>();
if (!fun)
return ctx->engine()->throwTypeError();
@@ -328,7 +335,7 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -370,7 +377,7 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
Scope scope(ctx);
- ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject());
+ ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -393,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();
}
@@ -409,29 +416,30 @@ Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *fun
{
}
-ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ 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())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
if (v4->hasException)
return Encode::undefined();
@@ -441,24 +449,24 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
return obj.asReturnedValue();
}
-ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<ScriptFunction> f(scope, static_cast<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())
- QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(scope.engine, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -466,7 +474,6 @@ ReturnedValue ScriptFunction::call(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.asObject())
{
this->scope = scope->d();
@@ -481,40 +488,42 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F
if (createProto) {
ScopedString name(s, function->name());
f->init(name, createProto);
- f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
+ 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) {
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(scope->d()->engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(scope->d()->engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
-ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(that)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ 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);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -524,32 +533,34 @@ ReturnedValue SimpleScriptFunction::construct(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);
ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
if (!result)
return callData->thisObject.asReturnedValue();
return result.asReturnedValue();
}
-ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<SimpleScriptFunction *>(that)->internalClass()->engine;
+ ExecutionEngine *v4 = static_cast<const SimpleScriptFunction *>(that)->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+ ExecutionContextSaver ctxSaver(scope);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that));
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ ctx.setVtable(CallContext::staticVTable());
ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f->d();
@@ -559,12 +570,13 @@ ReturnedValue SimpleScriptFunction::call(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()));
if (f->function()->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
+ QQmlPropertyCapture::registerQmlDependencies(v4, f->function()->compiledFunction);
return result->asReturnedValue();
}
@@ -575,7 +587,7 @@ Heap::Object *SimpleScriptFunction::protoForConstructor()
ScopedObject p(scope, protoProperty());
if (p)
return p->d();
- return scope.engine->objectPrototype.asObject()->d();
+ return scope.engine->objectPrototype()->d();
}
@@ -588,51 +600,53 @@ Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String
{
}
-ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
+ReturnedValue BuiltinFunction::construct(const Managed *f, CallData *)
{
- return static_cast<BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
+ return static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError();
}
-ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData)
{
- BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
+ const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ 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(Managed *that, CallData *callData)
+ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData)
{
- IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
+ const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope);
CallContext::Data ctx(v4);
- ctx.vtable = CallContext::staticVTable();
+ ctx.mm_data = 0;
+ 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);
@@ -650,24 +664,24 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb
Scope s(scope);
ScopedObject f(s, this);
- ScopedValue l(s, target->get(s.engine->id_length));
+ ScopedValue l(s, target->get(s.engine->id_length()));
int len = l->toUInt32();
if (boundArgs)
len -= boundArgs->size();
if (len < 0)
len = 0;
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(len));
ScopedProperty pd(s);
- pd->value = s.engine->thrower;
- pd->set = s.engine->thrower;
- f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ pd->value = s.engine->thrower();
+ pd->set = s.engine->thrower();
+ f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
-ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::call(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
@@ -685,9 +699,9 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
return t->call(callData);
}
-ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd)
{
- BoundFunction *f = static_cast<BoundFunction *>(that);
+ const BoundFunction *f = static_cast<const BoundFunction *>(that);
Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
@@ -707,7 +721,8 @@ ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
void BoundFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
{
BoundFunction::Data *o = static_cast<BoundFunction::Data *>(that);
- o->target->mark(e);
+ if (o->target)
+ o->target->mark(e);
o->boundThis.mark(e);
if (o->boundArgs)
o->boundArgs->mark(e);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 252ff40a1a..896bd2a4d2 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -33,10 +33,21 @@
#ifndef QV4FUNCTIONOBJECT_H
#define QV4FUNCTIONOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
QT_BEGIN_NAMESPACE
@@ -58,14 +69,14 @@ 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; }
- ExecutionContext *scope;
+ Pointer<ExecutionContext> scope;
Function *function;
};
@@ -74,7 +85,7 @@ struct FunctionCtor : FunctionObject {
};
struct FunctionPrototype : FunctionObject {
- FunctionPrototype(InternalClass *ic, QV4::Object *prototype);
+ FunctionPrototype();
};
struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
@@ -102,9 +113,9 @@ struct ScriptFunction : SimpleScriptFunction {
struct BoundFunction : FunctionObject {
BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
- FunctionObject *target;
+ Pointer<FunctionObject> target;
Value boundThis;
- MemberData *boundArgs;
+ Pointer<MemberData> boundArgs;
};
}
@@ -115,14 +126,16 @@ 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() { return d()->scope; }
- Function *function() { return d()->function; }
+ Heap::ExecutionContext *scope() const { return d()->scope; }
+ Function *function() const { return d()->function; }
- ReturnedValue name();
- unsigned int formalParameterCount() { return d()->formalParameterCount(); }
- unsigned int varCount() { return d()->varCount(); }
+ ReturnedValue name() const;
+ unsigned int formalParameterCount() const { return d()->formalParameterCount(); }
+ unsigned int varCount() const { return d()->varCount(); }
void init(String *name, bool createProto);
@@ -130,16 +143,14 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::construct;
using Object::call;
- static ReturnedValue construct(Managed *that, CallData *);
- static ReturnedValue call(Managed *that, CallData *d);
-
- static FunctionObject *cast(const Value &v) {
- return v.asFunctionObject();
- }
+ static ReturnedValue construct(const Managed *that, CallData *);
+ 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; }
@@ -152,16 +163,17 @@ struct Q_QML_EXPORT FunctionObject: Object {
};
template<>
-inline FunctionObject *value_cast(const Value &v) {
- return v.asFunctionObject();
+inline const FunctionObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : 0;
}
+
struct FunctionCtor: FunctionObject
{
V4_OBJECT2(FunctionCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct FunctionPrototype: FunctionObject
@@ -181,23 +193,23 @@ 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(Managed *, CallData *);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct IndexedBuiltinFunction: FunctionObject
{
V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *)
+ static ReturnedValue construct(const Managed *m, CallData *)
{
- return static_cast<IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
+ return static_cast<const IndexedBuiltinFunction *>(m)->engine()->throwTypeError();
}
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index,
@@ -211,9 +223,10 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop
struct SimpleScriptFunction: FunctionObject {
V4_OBJECT2(SimpleScriptFunction, FunctionObject)
+ V4_INTERNALCLASS(simpleScriptFunctionClass)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
Heap::Object *protoForConstructor();
};
@@ -221,8 +234,8 @@ struct SimpleScriptFunction: FunctionObject {
struct ScriptFunction: SimpleScriptFunction {
V4_OBJECT2(ScriptFunction, FunctionObject)
- static ReturnedValue construct(Managed *, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
@@ -231,15 +244,15 @@ 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() { return d()->target; }
+ Heap::FunctionObject *target() const { return d()->target; }
Value boundThis() const { return d()->boundThis; }
Heap::MemberData *boundArgs() const { return d()->boundArgs; }
- static ReturnedValue construct(Managed *, CallData *d);
- static ReturnedValue call(Managed *that, CallData *dd);
+ static ReturnedValue construct(const Managed *, CallData *d);
+ static ReturnedValue call(const Managed *that, CallData *dd);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 4b08194b60..01a21ea06d 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -34,6 +34,17 @@
#ifndef QV4GLOBAL_H
#define QV4GLOBAL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
#define V4_BOOTSTRAP
#endif
@@ -88,6 +99,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#define V4_ENABLE_JIT
#endif
+#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
+#define V4_ENABLE_JIT
#endif
// Black list some platforms
@@ -168,7 +181,7 @@ struct Property;
struct Value;
struct Lookup;
struct ArrayData;
-struct ManagedVTable;
+struct VTable;
struct BooleanObject;
struct NumberObject;
@@ -211,7 +224,6 @@ class WeakValue;
struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-struct QmlExtensions;
namespace Global {
enum {
@@ -277,8 +289,6 @@ struct PropertyAttributes
setConfigurable(!(f & Attr_NotConfigurable));
}
}
- PropertyAttributes(const PropertyAttributes &other) : m_all(other.m_all) {}
- PropertyAttributes & operator=(const PropertyAttributes &other) { m_all = other.m_all; return *this; }
void setType(Type t) { m_type = t; type_set = true; }
Type type() const { return type_set ? (Type)m_type : Generic; }
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 8e33cec57f..110a2c9089 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -32,13 +32,15 @@
****************************************************************************/
#include "qv4globalobject_p.h"
-#include "qv4mm_p.h"
-#include "qv4value_inl_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
#include "qv4context_p.h"
#include "qv4function_p.h"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4script_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -47,6 +49,7 @@
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
+#include "private/qtools_p.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
@@ -56,25 +59,8 @@
#include <wtf/MathExtras.h>
using namespace QV4;
-
-
-static inline char toHex(char c)
-{
- static const char hexnumbers[] = "0123456789ABCDEF";
- return hexnumbers[c & 0xf];
-}
-
-static int fromHex(QChar ch)
-{
- ushort c = ch.unicode();
- if ((c >= '0') && (c <= '9'))
- return c - '0';
- if ((c >= 'A') && (c <= 'F'))
- return c - 'A' + 10;
- if ((c >= 'a') && (c <= 'f'))
- return c - 'a' + 10;
- return -1;
-}
+using QtMiscUtils::toHexUpper;
+using QtMiscUtils::fromHex;
static QString escape(const QString &input)
{
@@ -93,16 +79,16 @@ static QString escape(const QString &input)
output.append(QChar(uc));
} else {
output.append('%');
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
} else {
output.append('%');
output.append('u');
- output.append(QLatin1Char(toHex(uc >> 12)));
- output.append(QLatin1Char(toHex(uc >> 8)));
- output.append(QLatin1Char(toHex(uc >> 4)));
- output.append(QLatin1Char(toHex(uc)));
+ output.append(QLatin1Char(toHexUpper(uc >> 12)));
+ output.append(QLatin1Char(toHexUpper(uc >> 8)));
+ output.append(QLatin1Char(toHexUpper(uc >> 4)));
+ output.append(QLatin1Char(toHexUpper(uc)));
}
}
return output;
@@ -119,10 +105,10 @@ static QString unescape(const QString &input)
if ((c == '%') && (i + 1 < length)) {
QChar a = input.at(i);
if ((a == 'u') && (i + 4 < length)) {
- int d3 = fromHex(input.at(i+1));
- int d2 = fromHex(input.at(i+2));
- int d1 = fromHex(input.at(i+3));
- int d0 = fromHex(input.at(i+4));
+ int d3 = fromHex(input.at(i+1).unicode());
+ int d2 = fromHex(input.at(i+2).unicode());
+ int d1 = fromHex(input.at(i+3).unicode());
+ int d0 = fromHex(input.at(i+4).unicode());
if ((d3 != -1) && (d2 != -1) && (d1 != -1) && (d0 != -1)) {
ushort uc = ushort((d3 << 12) | (d2 << 8) | (d1 << 4) | d0);
result.append(QChar(uc));
@@ -131,8 +117,8 @@ static QString unescape(const QString &input)
result.append(c);
}
} else {
- int d1 = fromHex(a);
- int d0 = fromHex(input.at(i+1));
+ int d1 = fromHex(a.unicode());
+ int d0 = fromHex(input.at(i+1).unicode());
if ((d1 != -1) && (d0 != -1)) {
c = (d1 << 4) | d0;
i += 2;
@@ -153,8 +139,8 @@ static const char uriUnescapedReserved[] = "-_.!~*'();/?:@&=+$,#";
static void addEscapeSequence(QString &output, uchar ch)
{
output.append(QLatin1Char('%'));
- output.append(QLatin1Char(toHex(ch >> 4)));
- output.append(QLatin1Char(toHex(ch & 0xf)));
+ output.append(QLatin1Char(toHexUpper(ch >> 4)));
+ output.append(QLatin1Char(toHexUpper(ch & 0xf)));
}
static QString encode(const QString &input, const char *unescapedSet, bool *ok)
@@ -246,8 +232,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (i + 2 >= length)
goto error;
- int d1 = fromHex(input.at(i+1));
- int d0 = fromHex(input.at(i+2));
+ int d1 = fromHex(input.at(i+1).unicode());
+ int d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -281,8 +267,8 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
if (input.at(i) != percent)
goto error;
- d1 = fromHex(input.at(i+1));
- d0 = fromHex(input.at(i+2));
+ d1 = fromHex(input.at(i+1).unicode());
+ d0 = fromHex(input.at(i+2).unicode());
if ((d1 == -1) || (d0 == -1))
goto error;
@@ -339,25 +325,24 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval())
{
Scope s(scope);
ScopedFunctionObject f(s, this);
- f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1));
+ f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1));
}
-ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
+ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
{
if (callData->argc < 1)
return Encode::undefined();
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
@@ -372,10 +357,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
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();
@@ -395,14 +380,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ctx->d()->strictMode = false;
ctx->d()->compilationUnit = function->compilationUnit;
- return function->code(ctx->engine(), function->codeData);
+ return Q_V4_PROFILE(ctx->engine(), function);
}
-ReturnedValue EvalFunction::call(Managed *that, CallData *callData)
+ReturnedValue EvalFunction::call(const Managed *that, CallData *callData)
{
// indirect call
- return static_cast<EvalFunction *>(that)->evalCall(callData, false);
+ return static_cast<const EvalFunction *>(that)->evalCall(callData, false);
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 74de233b47..ced85621de 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4GLOBALOBJECT_H
#define QV4GLOBALOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4functionobject_p.h"
@@ -52,10 +63,10 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
{
V4_OBJECT2(EvalFunction, FunctionObject)
- ReturnedValue evalCall(CallData *callData, bool directCall);
+ ReturnedValue evalCall(CallData *callData, bool directCall) const;
using Object::construct;
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct GlobalFunctions
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index 7937391ff7..605b06c685 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -33,6 +33,17 @@
#ifndef QV4IDENTIFIER_H
#define QV4IDENTIFIER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qstring.h>
QT_BEGIN_NAMESPACE
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 ff374225f4..3af9db963e 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -33,6 +33,17 @@
#ifndef QV4IDENTIFIERTABLE_H
#define QV4IDENTIFIERTABLE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4identifier_p.h"
#include "qv4string_p.h"
#include "qv4engine_p.h"
@@ -74,14 +85,16 @@ 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];
if (!entry || entry->isMarked())
continue;
entry->setMarkBit();
- Q_ASSERT(entry->gcGetVtable()->markObjects);
- entry->gcGetVtable()->markObjects(entry, e);
+ Q_ASSERT(entry->vtable()->markObjects);
+ entry->vtable()->markObjects(entry, e);
}
}
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index e4bd460966..90c6738c46 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -49,12 +49,13 @@
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 (callback.asFunctionObject())
+ if (qmlContext)
+ m_qmlContext.set(engine, *qmlContext);
+ if (callback.as<QV4::FunctionObject>())
m_callbackFunction.set(engine, callback);
m_resultObject.set(v4, resultValue(v4));
@@ -94,14 +95,14 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
{
if (!callback.isObject())
return;
- QV4::ExecutionEngine *v4 = callback.asObject()->engine();
+ QV4::ExecutionEngine *v4 = callback.as<QV4::Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, callback);
if (!f)
return;
QV4::ScopedCallData callData(scope, 1);
- callData->thisObject = v4->globalObject()->asReturnedValue();
+ callData->thisObject = v4->globalObject->asReturnedValue();
callData->args[0] = status;
f->call(callData);
if (scope.hasException())
@@ -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)
@@ -176,7 +177,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QV4::Scope scope(ctx->engine());
- QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine);
+ QQmlContextData *context = scope.engine->callingQmlContext();
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
@@ -184,18 +185,16 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow()));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (ctx->argc() >= 2 && ctx->args()[1].asFunctionObject())
+ if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>())
callbackFunction = ctx->args()[1];
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()));
}
}
@@ -224,7 +223,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QV4::ScopedValue ex(scope, scope.engine->catchException());
result = resultValue(scope.engine, Exception);
QV4::ScopedString exception(scope, scope.engine->newString(QStringLiteral("exception")));
- result->asObject()->put(exception, ex);
+ result->as<QV4::Object>()->put(exception, ex);
} else {
result = resultValue(scope.engine, Ok);
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 5dc94e8555..3e3cf5e770 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -50,7 +50,7 @@
#include <private/qqmlcontext_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4context_p.h>
QT_BEGIN_NAMESPACE
@@ -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 3289058cb7..5b91925ede 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -33,6 +33,17 @@
#ifndef QV4INTERNALCLASS_H
#define QV4INTERNALCLASS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include <QHash>
@@ -46,7 +57,7 @@ struct String;
struct ExecutionEngine;
struct Object;
struct Identifier;
-struct ManagedVTable;
+struct VTable;
struct PropertyHashData;
struct PropertyHash
@@ -233,6 +244,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 e7905974df..2e5283c639 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -38,8 +38,8 @@
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4runtime_p.h>
+#include "qv4string_p.h"
-#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -62,33 +62,6 @@ static int indent = 0;
DEFINE_OBJECT_VTABLE(JsonObject);
-class JsonParser
-{
-public:
- JsonParser(ExecutionEngine *engine, const QChar *json, int length);
-
- ReturnedValue parse(QJsonParseError *error);
-
-private:
- inline bool eatSpace();
- inline QChar nextToken();
-
- ReturnedValue parseObject();
- ReturnedValue parseArray();
- bool parseMember(Object *o);
- bool parseString(QString *string);
- bool parseValue(Value *val);
- bool parseNumber(Value *val);
-
- ExecutionEngine *engine;
- const QChar *head;
- const QChar *json;
- const QChar *end;
-
- int nestingLevel;
- QJsonParseError::ParseError lastError;
-};
-
static const int nestingLimit = 1024;
@@ -639,17 +612,22 @@ bool JsonParser::parseString(QString *string)
struct Stringify
{
- ExecutionContext *ctx;
+ ExecutionEngine *v4;
FunctionObject *replacerFunction;
- // ### GC
- QVector<Heap::String *> propertyList;
+ QV4::String *propertyList;
+ int propertyListSize;
QString gap;
QString indent;
+ QStack<Object *> stack;
- // ### GC
- QStack<Heap::Object *> stack;
+ bool stackContains(Object *o) {
+ for (int i = 0; i < stack.size(); ++i)
+ if (stack.at(i)->d() == o->d())
+ return true;
+ return false;
+ }
- Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {}
+ Stringify(ExecutionEngine *e) : v4(e), replacerFunction(0), propertyList(0), propertyListSize(0) {}
QString Str(const QString &key, const Value &v);
QString JA(ArrayObject *a);
@@ -701,26 +679,26 @@ static QString quote(const QString &str)
QString Stringify::Str(const QString &key, const Value &v)
{
- Scope scope(ctx);
+ Scope scope(v4);
ScopedValue value(scope, v);
ScopedObject o(scope, value);
if (o) {
- ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
+ ScopedString s(scope, v4->newString(QStringLiteral("toJSON")));
ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
ScopedCallData callData(scope, 1);
callData->thisObject = value;
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
value = toJSON->call(callData);
}
}
if (replacerFunction) {
- ScopedObject holder(scope, ctx->d()->engine->newObject());
+ ScopedObject holder(scope, v4->newObject());
holder->put(scope.engine, QString(), value);
ScopedCallData callData(scope, 2);
- callData->args[0] = ctx->d()->engine->newString(key);
+ callData->args[0] = v4->newString(key);
callData->args[1] = value;
callData->thisObject = holder;
value = replacerFunction->call(callData);
@@ -728,11 +706,11 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (NumberObject *n = o->asNumberObject())
+ if (NumberObject *n = o->as<NumberObject>())
value = Encode(n->value());
- else if (StringObject *so = o->asStringObject())
- value = so->d()->value;
- else if (BooleanObject *b =o->asBooleanObject())
+ else if (StringObject *so = o->as<StringObject>())
+ value = so->d()->string;
+ else if (BooleanObject *b = o->as<BooleanObject>())
value = Encode(b->value());
}
@@ -750,8 +728,8 @@ QString Stringify::Str(const QString &key, const Value &v)
o = value->asReturnedValue();
if (o) {
- if (!o->asFunctionObject()) {
- if (o->asArrayObject()) {
+ if (!o->as<FunctionObject>()) {
+ if (o->as<ArrayObject>()) {
return JA(static_cast<ArrayObject *>(o.getPointer()));
} else {
return JO(o);
@@ -777,20 +755,20 @@ QString Stringify::makeMember(const QString &key, const Value &v)
QString Stringify::JO(Object *o)
{
- if (stack.contains(o->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(o)) {
+ v4->throwTypeError();
return QString();
}
- Scope scope(ctx);
+ Scope scope(v4);
QString result;
- stack.push(o->d());
+ stack.push(o);
QString stepback = indent;
indent += gap;
QStringList partial;
- if (propertyList.isEmpty()) {
+ if (!propertyListSize) {
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -805,11 +783,13 @@ QString Stringify::JO(Object *o)
partial += member;
}
} else {
- ScopedString s(scope);
- for (int i = 0; i < propertyList.size(); ++i) {
+ ScopedValue v(scope);
+ for (int i = 0; i < propertyListSize; ++i) {
bool exists;
- s = propertyList.at(i);
- ScopedValue v(scope, o->get(s, &exists));
+ String *s = propertyList + i;
+ if (!s)
+ continue;
+ v = o->get(s, &exists);
if (!exists)
continue;
QString member = makeMember(s->toQString(), v);
@@ -821,10 +801,11 @@ QString Stringify::JO(Object *o)
if (partial.isEmpty()) {
result = QStringLiteral("{}");
} else if (gap.isEmpty()) {
- result = QStringLiteral("{") + partial.join(QLatin1Char(',')) + QStringLiteral("}");
+ result = QStringLiteral("{") + partial.join(QLatin1Char(',')) + QLatin1Char('}');
} else {
QString separator = QStringLiteral(",\n") + indent;
- result = QStringLiteral("{\n") + indent + partial.join(separator) + QStringLiteral("\n") + stepback + QStringLiteral("}");
+ result = QStringLiteral("{\n") + indent + partial.join(separator) + QLatin1Char('\n')
+ + stepback + QLatin1Char('}');
}
indent = stepback;
@@ -834,15 +815,15 @@ QString Stringify::JO(Object *o)
QString Stringify::JA(ArrayObject *a)
{
- if (stack.contains(a->d())) {
- ctx->engine()->throwTypeError();
+ if (stackContains(a)) {
+ v4->throwTypeError();
return QString();
}
Scope scope(a->engine());
QString result;
- stack.push(a->d());
+ stack.push(a);
QString stepback = indent;
indent += gap;
@@ -878,10 +859,9 @@ QString Stringify::JA(ArrayObject *a)
}
-Heap::JsonObject::JsonObject(ExecutionEngine *e)
- : Heap::Object(e->emptyClass, e->objectPrototype.asObject())
+Heap::JsonObject::JsonObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject o(scope, this);
o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2);
@@ -911,32 +891,38 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
{
Scope scope(ctx);
- Stringify stringify(ctx);
+ Stringify stringify(scope.engine);
ScopedObject o(scope, ctx->argument(1));
if (o) {
- stringify.replacerFunction = o->asFunctionObject();
+ stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
uint arrayLen = o->getLength();
- ScopedValue v(scope);
+ stringify.propertyList = static_cast<QV4::String *>(scope.alloc(arrayLen));
for (uint i = 0; i < arrayLen; ++i) {
- v = o->getIndexed(i);
- if (v->asNumberObject() || v->asStringObject() || v->isNumber())
- v = RuntimeHelpers::toString(scope.engine, v);
- if (v->isString()) {
- String *s = v->stringValue();
- if (!stringify.propertyList.contains(s->d()))
- stringify.propertyList.append(s->d());
+ Value *v = stringify.propertyList + i;
+ *v = o->getIndexed(i);
+ if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
+ *v = RuntimeHelpers::toString(scope.engine, *v);
+ if (!v->isString()) {
+ v->setM(0);
+ } else {
+ for (uint j = 0; j <i; ++j) {
+ if (stringify.propertyList[j].m() == v->m()) {
+ v->setM(0);
+ break;
+ }
+ }
}
}
}
}
ScopedValue s(scope, ctx->argument(2));
- if (NumberObject *n = s->asNumberObject())
+ if (NumberObject *n = s->as<NumberObject>())
s = Encode(n->value());
- else if (StringObject *so = s->asStringObject())
- s = so->d()->value;
+ else if (StringObject *so = s->as<StringObject>())
+ s = so->d()->string;
if (s->isNumber()) {
stringify.gap = QString(qMin(10, (int)s->toInteger()), ' ');
@@ -957,7 +943,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())
@@ -986,7 +972,7 @@ QJsonValue JsonObject::toJsonValue(const Value &value, V4ObjectSet &visitedObjec
return QJsonValue(value.toQString());
Q_ASSERT(value.isObject());
- Scope scope(value.asObject()->engine());
+ Scope scope(value.as<Object>()->engine());
ScopedArrayObject a(scope, value);
if (a)
return toJsonArray(a, visitedObjects);
@@ -1009,22 +995,22 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs
return o.asReturnedValue();
}
-QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
+QJsonObject JsonObject::toJsonObject(const Object *o, V4ObjectSet &visitedObjects)
{
QJsonObject result;
- if (!o || o->asFunctionObject())
+ if (!o || o->as<FunctionObject>())
return result;
Scope scope(o->engine());
- if (visitedObjects.contains(o->d())) {
+ if (visitedObjects.contains(ObjectItem(o))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
return result;
}
- visitedObjects.insert(o->d());
+ visitedObjects.insert(ObjectItem(o));
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -1035,11 +1021,11 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
break;
QString key = name->toQStringNoThrow();
- if (!val->asFunctionObject())
+ if (!val->as<FunctionObject>())
result.insert(key, toJsonValue(val, visitedObjects));
}
- visitedObjects.remove(o->d());
+ visitedObjects.remove(ObjectItem(o));
return result;
}
@@ -1057,7 +1043,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
return a.asReturnedValue();
}
-QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
+QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects)
{
QJsonArray result;
if (!a)
@@ -1065,25 +1051,25 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
Scope scope(a->engine());
- if (visitedObjects.contains(a->d())) {
+ if (visitedObjects.contains(ObjectItem(a))) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty array (and no error is thrown).
return result;
}
- visitedObjects.insert(a->d());
+ visitedObjects.insert(ObjectItem(a));
ScopedValue v(scope);
quint32 length = a->getLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
- if (v->asFunctionObject())
+ if (v->as<FunctionObject>())
v = Encode::null();
result.append(toJsonValue(v, visitedObjects));
}
- visitedObjects.remove(a->d());
+ visitedObjects.remove(ObjectItem(a));
return result;
}
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 81a783ee92..6a6e863bf6 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -33,10 +33,23 @@
#ifndef QV4JSONOBJECT_H
#define QV4JSONOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include <qjsonarray.h>
#include <qjsonobject.h>
#include <qjsonvalue.h>
+#include <qjsondocument.h>
+#include <qhash.h>
QT_BEGIN_NAMESPACE
@@ -45,17 +58,28 @@ namespace QV4 {
namespace Heap {
struct JsonObject : Object {
- JsonObject(ExecutionEngine *e);
+ JsonObject();
};
}
+struct ObjectItem {
+ const QV4::Object *o;
+ ObjectItem(const QV4::Object *o) : o(o) {}
+};
+
+inline bool operator ==(const ObjectItem &a, const ObjectItem &b)
+{ return a.o->d() == b.o->d(); }
+
+inline int qHash(const ObjectItem &i, uint seed = 0)
+{ return ::qHash((void *)i.o->d(), seed); }
+
struct JsonObject : Object {
Q_MANAGED_TYPE(JsonObject)
V4_OBJECT2(JsonObject, Object)
private:
- // ### GC
- typedef QSet<QV4::Heap::Base *> V4ObjectSet;
+
+ typedef QSet<ObjectItem> V4ObjectSet;
public:
static ReturnedValue method_parse(CallContext *ctx);
@@ -67,18 +91,45 @@ public:
static inline QJsonValue toJsonValue(const QV4::Value &value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
- static inline QJsonObject toJsonObject(QV4::Object *o)
+ static inline QJsonObject toJsonObject(const QV4::Object *o)
{ V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); }
- static inline QJsonArray toJsonArray(QV4::ArrayObject *a)
+ static inline QJsonArray toJsonArray(const QV4::ArrayObject *a)
{ V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); }
private:
static QJsonValue toJsonValue(const QV4::Value &value, V4ObjectSet &visitedObjects);
- static QJsonObject toJsonObject(Object *o, V4ObjectSet &visitedObjects);
- static QJsonArray toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects);
+ static QJsonObject toJsonObject(const Object *o, V4ObjectSet &visitedObjects);
+ static QJsonArray toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObjects);
};
+class JsonParser
+{
+public:
+ JsonParser(ExecutionEngine *engine, const QChar *json, int length);
+
+ ReturnedValue parse(QJsonParseError *error);
+
+private:
+ inline bool eatSpace();
+ inline QChar nextToken();
+
+ ReturnedValue parseObject();
+ ReturnedValue parseArray();
+ bool parseMember(Object *o);
+ bool parseString(QString *string);
+ bool parseValue(Value *val);
+ bool parseNumber(Value *val);
+
+ ExecutionEngine *engine;
+ const QChar *head;
+ const QChar *json;
+ const QChar *end;
+
+ int nestingLevel;
+ QJsonParseError::ParseError lastError;
+};
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 82b20337cb..d97abdb461 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -33,6 +33,7 @@
#include "qv4lookup_p.h"
#include "qv4functionobject_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -42,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) {
@@ -52,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;
@@ -64,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;
@@ -72,11 +75,11 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
return Primitive::emptyValue().asReturnedValue();
}
-ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
+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;
@@ -85,7 +88,8 @@ ReturnedValue Lookup::lookup(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;
@@ -97,7 +101,8 @@ ReturnedValue Lookup::lookup(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;
@@ -123,7 +128,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -164,11 +169,11 @@ 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) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
@@ -200,7 +205,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
uint idx = index.asArrayIndex();
if (idx < UINT_MAX) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = value;
return;
@@ -224,7 +229,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
Object *o = object.objectValue();
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
- Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) {
s->data(idx) = v;
return;
@@ -235,7 +240,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value
ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (Object *o = object.asObject())
+ if (const Object *o = object.as<Object>())
return o->getLookup(l);
Object *proto;
@@ -244,14 +249,14 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
case Value::Null_Type:
return engine->throwTypeError();
case Value::Boolean_Type:
- proto = engine->booleanPrototype.asObject();
+ proto = engine->booleanPrototype();
break;
case Value::Managed_Type: {
Q_ASSERT(object.isString());
- proto = engine->stringPrototype.asObject();
+ proto = engine->stringPrototype();
Scope scope(engine);
- ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(engine->id_length)) {
+ 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;
return stringLengthGetter(l, engine, object);
@@ -260,7 +265,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
}
case Value::Integer_Type:
default: // Number
- proto = engine->numberPrototype.asObject();
+ proto = engine->numberPrototype();
}
PropertyAttributes attrs;
@@ -291,7 +296,7 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const
Lookup l1 = *l;
if (l1.getter == Lookup::getter0 || l1.getter == Lookup::getter1) {
- if (Object *o = object.asObject()) {
+ if (const Object *o = object.as<Object>()) {
ReturnedValue v = o->getLookup(l);
Lookup l2 = *l;
@@ -328,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);
}
@@ -339,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);
}
@@ -352,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);
}
@@ -368,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();
}
}
}
@@ -383,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);
@@ -398,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);
@@ -415,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;
@@ -434,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();
@@ -456,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();
@@ -481,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();
@@ -501,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);
@@ -513,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);
@@ -525,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();
@@ -545,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();
@@ -560,7 +565,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (String *s = object.asString())
+ if (const String *s = object.as<String>())
return Encode(s->d()->length());
l->getter = getterGeneric;
@@ -569,8 +574,8 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
{
- if (ArrayObject *a = object.asArrayObject())
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ if (const ArrayObject *a = object.as<ArrayObject>())
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
l->getter = getterGeneric;
return getterGeneric(l, engine, object);
@@ -579,7 +584,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, cons
ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -602,15 +607,15 @@ 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);
}
ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ 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);
@@ -618,10 +623,10 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ 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);
@@ -629,13 +634,13 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
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();
}
}
}
@@ -645,10 +650,10 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ 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();
@@ -662,11 +667,11 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = engine->globalObject();
+ Object *o = engine->globalObject;
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();
@@ -680,14 +685,14 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
{
- Heap::Object *o = engine->globalObject()->d();
+ Heap::Object *o = engine->globalObject->d();
if (l->classList[0] == o->internalClass) {
o = o->prototype;
if (l->classList[1] == o->internalClass) {
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();
@@ -701,7 +706,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
return globalGetterGeneric(l, engine);
}
-void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Scope scope(engine);
ScopedObject o(scope, object);
@@ -709,18 +714,18 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &obje
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;
}
o->setLookup(l, value);
}
-void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Lookup l1 = *l;
- if (Object *o = object.asObject()) {
+ if (Object *o = object.as<Object>()) {
o->setLookup(l, value);
if (l->setter == Lookup::setter0) {
@@ -735,36 +740,34 @@ void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &o
setterFallback(l, engine, object, value);
}
-void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
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);
}
}
-void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
- o->memberData()->data[l->index] = value;
+ *o->propertyData(l->index) = value;
return;
}
setterTwoClasses(l, engine, object, value);
}
-void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ 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;
}
}
@@ -773,16 +776,14 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
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;
}
}
@@ -791,18 +792,16 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
Heap::Object *p = o->prototype();
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;
}
}
@@ -812,16 +811,16 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &obje
setterFallback(l, engine, object, value);
}
-void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value)
+void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.asManaged());
+ 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/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 88397dc36c..77ad1a7b65 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -33,6 +33,17 @@
#ifndef QV4LOOKUP_H
#define QV4LOOKUP_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4runtime_p.h"
#include "qv4engine_p.h"
@@ -51,7 +62,7 @@ struct Lookup {
void (*indexedSetter)(Lookup *l, const Value &object, const Value &index, const Value &v);
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
- void (*setter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &v);
+ void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
};
union {
ExecutionEngine *engine;
@@ -107,17 +118,17 @@ struct Lookup {
static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine);
static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine);
- static void setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
- static void setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value);
+ static void setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static void setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs);
- ReturnedValue lookup(Object *obj, PropertyAttributes *attrs);
+ ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs);
};
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index c4b9fc597e..e2de36d18e 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -32,13 +32,13 @@
****************************************************************************/
#include "qv4managed_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4errorobject_p.h"
using namespace QV4;
-const ManagedVTable Managed::static_vtbl =
+const VTable Managed::static_vtbl =
{
0,
Managed::IsExecutionContext,
@@ -59,7 +59,7 @@ const ManagedVTable Managed::static_vtbl =
QString Managed::className() const
{
const char *s = 0;
- switch (Type(d()->vtable->type)) {
+ switch (Type(d()->vtable()->type)) {
case Type_Invalid:
case Type_String:
return QString();
@@ -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/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index aa3e668eef..6a1bd7a9a4 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -33,16 +33,27 @@
#ifndef QMLJS_MANAGED_H
#define QMLJS_MANAGED_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
+#include <private/qv4heap_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
#define Q_MANAGED_CHECK \
- template <typename _T> inline void qt_check_for_QMANAGED_macro(const _T *_q_argument) const \
+ template <typename Type> inline void qt_check_for_QMANAGED_macro(const Type *_q_argument) const \
{ int i = qYouForgotTheQ_MANAGED_Macro(this, _q_argument); i = i + 1; }
template <typename T>
@@ -65,10 +76,10 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
Q_MANAGED_CHECK \
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
- static const QV4::ManagedVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
+ static const QV4::VTable static_vtbl; \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
#define V4_MANAGED(DataClass, superClass) \
private: \
@@ -84,31 +95,6 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
(classname::func == QV4::Managed::func ? 0 : classname::func)
-struct GCDeletable
-{
- GCDeletable() : next(0), lastCall(false) {}
- virtual ~GCDeletable() {}
- GCDeletable *next;
- bool lastCall;
-};
-
-struct ManagedVTable
-{
- const ManagedVTable * const parent;
- uint isExecutionContext : 1;
- uint isString : 1;
- uint isObject : 1;
- uint isFunctionObject : 1;
- uint isErrorObject : 1;
- uint isArrayData : 1;
- uint unused : 18;
- uint type : 8;
- const char *className;
- void (*destroy)(Heap::Base *);
- void (*markObjects)(Heap::Base *, ExecutionEngine *e);
- bool (*isEqualTo)(Managed *m, Managed *other);
-};
-
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
@@ -127,7 +113,7 @@ struct ManagedVTable
}
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
struct Q_QML_PRIVATE_EXPORT Managed : Value
{
@@ -147,8 +133,6 @@ private:
public:
- inline void mark(QV4::ExecutionEngine *engine);
-
enum Type {
Type_Invalid,
Type_String,
@@ -173,55 +157,15 @@ public:
};
Q_MANAGED_TYPE(Invalid)
- template <typename T>
- T *as() {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
- template <typename T>
- const T *as() const {
- Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
- static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
-#endif
- const ManagedVTable *vt = d()->vtable;
- while (vt) {
- if (vt == T::staticVTable())
- return static_cast<T *>(this);
- vt = vt->parent;
- }
- return 0;
- }
-
- String *asString() { return d()->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
- Object *asObject() { return d()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
- ArrayObject *asArrayObject() { return d()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
- FunctionObject *asFunctionObject() { return d()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
- BooleanObject *asBooleanObject() { return d()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
- NumberObject *asNumberObject() { return d()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
- StringObject *asStringObject() { return d()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
- DateObject *asDateObject() { return d()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
- ErrorObject *asErrorObject() { return d()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
- ArgumentsObject *asArgumentsObject() { return d()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
-
- bool isListType() const { return d()->vtable->type == Type_QmlSequence; }
-
- bool isArrayObject() const { return d()->vtable->type == Type_ArrayObject; }
- bool isStringObject() const { return d()->vtable->type == Type_StringObject; }
+ bool isListType() const { return d()->vtable()->type == Type_QmlSequence; }
+
+ bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; }
+ bool isStringObject() const { return d()->vtable()->type == Type_StringObject; }
QString className() const;
bool isEqualTo(const Managed *other) const
- { return d()->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
+ { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
static bool isEqualTo(Managed *m, Managed *other);
@@ -237,37 +181,15 @@ private:
template<>
-inline Managed *value_cast(const Value &v) {
- return v.asManaged();
-}
-
-template<typename T>
-inline T *managed_cast(Managed *m)
-{
- return m ? m->as<T>() : 0;
+inline const Managed *Value::as() const {
+ if (isManaged())
+ return managed();
+ return 0;
}
template<>
-inline String *managed_cast(Managed *m)
-{
- return m ? m->asString() : 0;
-}
-template<>
-inline Object *managed_cast(Managed *m)
-{
- return m ? m->asObject() : 0;
-}
-template<>
-inline FunctionObject *managed_cast(Managed *m)
-{
- return m ? m->asFunctionObject() : 0;
-}
-
-inline Value Value::fromManaged(Managed *m)
-{
- if (!m)
- return QV4::Primitive::undefinedValue();
- return *m;
+inline const Object *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isObject ? objectValue() : 0;
}
}
diff --git a/src/qml/jsruntime/qv4math_p.h b/src/qml/jsruntime/qv4math_p.h
index 4f550752aa..cf627bcc5d 100644
--- a/src/qml/jsruntime/qv4math_p.h
+++ b/src/qml/jsruntime/qv4math_p.h
@@ -33,6 +33,17 @@
#ifndef QMLJS_MATH_H
#define QMLJS_MATH_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <qglobal.h>
#include <QtCore/qnumeric.h>
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 473e05bf88..3d3ac84576 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.asObject())
+Heap::MathObject::MathObject()
{
- Scope scope(e);
+ Scope scope(internalClass->engine);
ScopedObject m(scope, this);
m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(M_E));
@@ -278,10 +277,15 @@ Q_GLOBAL_STATIC(QThreadStorage<bool *>, seedCreatedStorage);
ReturnedValue MathObject::method_random(CallContext *context)
{
if (!seedCreatedStorage()->hasLocalData()) {
- qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) ^ reinterpret_cast<quintptr>(context));
+ int msecs = QTime(0,0,0).msecsTo(QTime::currentTime());
+ Q_ASSERT(msecs >= 0);
+ qsrand(uint(uint(msecs) ^ reinterpret_cast<quintptr>(context)));
seedCreatedStorage()->setLocalData(new bool(true));
}
- return Encode(qrand() / (double) RAND_MAX);
+ // rand()/qrand() return a value where the upperbound is RAND_MAX inclusive. So, instead of
+ // dividing by RAND_MAX (which would return 0..RAND_MAX inclusive), we divide by RAND_MAX + 1.
+ qint64 upperLimit = qint64(RAND_MAX) + 1;
+ return Encode(qrand() / double(upperLimit));
}
ReturnedValue MathObject::method_round(CallContext *context)
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 472b2020b1..a233f74367 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4MATHOBJECT_H
#define QV4MATHOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
QT_BEGIN_NAMESPACE
@@ -42,7 +53,7 @@ namespace QV4 {
namespace Heap {
struct MathObject : Object {
- MathObject(ExecutionEngine *e);
+ MathObject();
};
}
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index 03dfee3dcf..20f8d9ec0f 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -32,7 +32,8 @@
****************************************************************************/
#include "qv4memberdata_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include "qv4value_p.h"
using namespace QV4;
@@ -45,20 +46,30 @@ void MemberData::markObjects(Heap::Base *that, ExecutionEngine *e)
m->data[i].mark(e);
}
-Heap::MemberData *MemberData::reallocate(ExecutionEngine *e, Heap::MemberData *old, uint idx)
+static Heap::MemberData *reallocateHelper(ExecutionEngine *e, Heap::MemberData *old, uint n)
{
- uint s = old ? old->size : 0;
- if (idx < s)
- return old;
-
- int newAlloc = qMax((uint)4, 2*idx);
- uint alloc = sizeof(Heap::MemberData) + (newAlloc)*sizeof(Value);
+ uint alloc = sizeof(Heap::MemberData) + (n)*sizeof(Value);
Scope scope(e);
Scoped<MemberData> newMemberData(scope, e->memoryManager->allocManaged<MemberData>(alloc));
if (old)
- memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + s*sizeof(Value));
+ memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + old->size * sizeof(Value));
else
new (newMemberData->d()) Heap::MemberData;
- newMemberData->d()->size = newAlloc;
+ newMemberData->d()->size = n;
return newMemberData->d();
}
+
+Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n)
+{
+ return reallocateHelper(e, 0, n);
+}
+
+Heap::MemberData *MemberData::reallocate(ExecutionEngine *e, Heap::MemberData *old, uint n)
+{
+ uint s = old ? old->size : 0;
+ if (n < s)
+ return old;
+
+ // n is multiplied by two to leave room for growth
+ return reallocateHelper(e, old, qMax((uint)4, 2*n));
+}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 4c7cfa47cb..12f407e869 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -33,6 +33,17 @@
#ifndef QV4MEMBERDATA_H
#define QV4MEMBERDATA_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4managed_p.h"
@@ -61,7 +72,8 @@ struct MemberData : Managed
Value *data() { return d()->data; }
inline uint size() const { return d()->size; }
- static Heap::MemberData *reallocate(QV4::ExecutionEngine *e, Heap::MemberData *old, uint idx);
+ static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n);
+ static Heap::MemberData *reallocate(QV4::ExecutionEngine *e, Heap::MemberData *old, uint n);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
deleted file mode 100644
index 64491e1376..0000000000
--- a/src/qml/jsruntime/qv4mm.cpp
+++ /dev/null
@@ -1,651 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4engine_p.h"
-#include "qv4object_p.h"
-#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
-#include "qv4qobjectwrapper_p.h"
-#include <qqmlengine.h>
-#include "PageAllocation.h"
-#include "StdLibExtras.h"
-
-#include <QTime>
-#include <QVector>
-#include <QVector>
-#include <QMap>
-
-#include <iostream>
-#include <cstdlib>
-#include <algorithm>
-#include "qv4alloca_p.h"
-#include "qv4profiling_p.h"
-
-#ifdef V4_USE_VALGRIND
-#include <valgrind/valgrind.h>
-#include <valgrind/memcheck.h>
-#endif
-
-#if OS(QNX)
-#include <sys/storage.h> // __tls()
-#endif
-
-#if USE(PTHREADS) && HAVE(PTHREAD_NP_H)
-#include <pthread_np.h>
-#endif
-
-using namespace WTF;
-
-QT_BEGIN_NAMESPACE
-
-using namespace QV4;
-
-struct MemoryManager::Data
-{
- struct ChunkHeader {
- Heap::Base freeItems;
- ChunkHeader *nextNonFull;
- char *itemStart;
- char *itemEnd;
- int itemSize;
- };
-
- bool gcBlocked;
- bool aggressiveGC;
- bool gcStats;
- ExecutionEngine *engine;
-
- enum { MaxItemSize = 512 };
- ChunkHeader *nonFullChunks[MaxItemSize/16];
- uint nChunks[MaxItemSize/16];
- uint availableItems[MaxItemSize/16];
- uint allocCount[MaxItemSize/16];
- int totalItems;
- int totalAlloc;
- uint maxShift;
- std::size_t maxChunkSize;
- QVector<PageAllocation> heapChunks;
- std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
- std::size_t unmanagedHeapSizeGCLimit;
-
- struct LargeItem {
- LargeItem *next;
- size_t size;
- void *data;
-
- Heap::Base *heapObject() {
- return reinterpret_cast<Heap::Base *>(&data);
- }
- };
-
- LargeItem *largeItems;
- std::size_t totalLargeItemsAllocated;
-
- GCDeletable *deletable;
-
- // statistics:
-#ifdef DETAILED_MM_STATS
- QVector<unsigned> allocSizeCounters;
-#endif // DETAILED_MM_STATS
-
- Data()
- : gcBlocked(false)
- , engine(0)
- , totalItems(0)
- , totalAlloc(0)
- , maxShift(6)
- , maxChunkSize(32*1024)
- , unmanagedHeapSize(0)
- , unmanagedHeapSizeGCLimit(64 * 1024)
- , largeItems(0)
- , totalLargeItemsAllocated(0)
- , deletable(0)
- {
- memset(nonFullChunks, 0, sizeof(nonFullChunks));
- memset(nChunks, 0, sizeof(nChunks));
- memset(availableItems, 0, sizeof(availableItems));
- memset(allocCount, 0, sizeof(allocCount));
- aggressiveGC = !qgetenv("QV4_MM_AGGRESSIVE_GC").isEmpty();
- gcStats = !qgetenv("QV4_MM_STATS").isEmpty();
-
- QByteArray overrideMaxShift = qgetenv("QV4_MM_MAXBLOCK_SHIFT");
- bool ok;
- uint override = overrideMaxShift.toUInt(&ok);
- if (ok && override <= 11 && override > 0)
- maxShift = override;
-
- QByteArray maxChunkString = qgetenv("QV4_MM_MAX_CHUNK_SIZE");
- std::size_t tmpMaxChunkSize = maxChunkString.toUInt(&ok);
- if (ok)
- maxChunkSize = tmpMaxChunkSize;
- }
-
- ~Data()
- {
- for (QVector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
- Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
- i->deallocate();
- }
- }
-};
-
-namespace {
-
-bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine, std::size_t *unmanagedHeapSize)
-{
- Q_ASSERT(unmanagedHeapSize);
-
- bool isEmpty = true;
- Heap::Base *tail = &header->freeItems;
-// qDebug("chunkStart @ %p, size=%x, pos=%x", header->itemStart, header->itemSize, header->itemSize>>4);
-#ifdef V4_USE_VALGRIND
- VALGRIND_DISABLE_ERROR_REPORTING;
-#endif
- for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
- Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
-// qDebug("chunk @ %p, in use: %s, mark bit: %s",
-// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false"));
-
- Q_ASSERT((qintptr) item % 16 == 0);
-
- if (m->isMarked()) {
- Q_ASSERT(m->inUse());
- m->clearMarkBit();
- isEmpty = false;
- ++(*itemsInUse);
- } else {
- if (m->inUse()) {
-// qDebug() << "-- collecting it." << m << tail << m->nextFree();
-#ifdef V4_USE_VALGRIND
- VALGRIND_ENABLE_ERROR_REPORTING;
-#endif
- if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->gcGetVtable()->isString) {
- std::size_t heapBytes = static_cast<Heap::String *>(m)->retainedTextSize();
- Q_ASSERT(*unmanagedHeapSize >= heapBytes);
-// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes";
- *unmanagedHeapSize -= heapBytes;
- }
-
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
-
- memset(m, 0, header->itemSize);
-#ifdef V4_USE_VALGRIND
- VALGRIND_DISABLE_ERROR_REPORTING;
- VALGRIND_MEMPOOL_FREE(engine->memoryManager, m);
-#endif
- Q_V4_PROFILE_DEALLOC(engine, m, header->itemSize, Profiling::SmallItem);
- ++(*itemsInUse);
- }
- // Relink all free blocks to rewrite references to any released chunk.
- tail->setNextFree(m);
- tail = m;
- }
- }
- tail->setNextFree(0);
-#ifdef V4_USE_VALGRIND
- VALGRIND_ENABLE_ERROR_REPORTING;
-#endif
- return isEmpty;
-}
-
-} // namespace
-
-MemoryManager::MemoryManager(ExecutionEngine *engine)
- : m_d(new Data)
- , m_persistentValues(new PersistentValueStorage(engine))
- , m_weakValues(new PersistentValueStorage(engine))
-{
-#ifdef V4_USE_VALGRIND
- VALGRIND_CREATE_MEMPOOL(this, 0, true);
-#endif
- m_d->engine = engine;
-}
-
-Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize)
-{
- if (m_d->aggressiveGC)
- runGC();
-#ifdef DETAILED_MM_STATS
- willAllocate(size);
-#endif // DETAILED_MM_STATS
-
- Q_ASSERT(size >= 16);
- Q_ASSERT(size % 16 == 0);
-
-// qDebug() << "unmanagedHeapSize:" << m_d->unmanagedHeapSize << "limit:" << m_d->unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize;
- m_d->unmanagedHeapSize += unmanagedSize;
- bool didGCRun = false;
- if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) {
- runGC();
-
- if (m_d->unmanagedHeapSizeGCLimit <= m_d->unmanagedHeapSize)
- 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);
- didGCRun = true;
- }
-
- size_t pos = size >> 4;
-
- // doesn't fit into a small bucket
- if (size >= MemoryManager::Data::MaxItemSize) {
- if (!didGCRun && m_d->totalLargeItemsAllocated > 8 * 1024 * 1024)
- runGC();
-
- // 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),
- Profiling::LargeItem)));
- memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
- item->next = m_d->largeItems;
- item->size = size;
- m_d->largeItems = item;
- m_d->totalLargeItemsAllocated += size;
- return item->heapObject();
- }
-
- Heap::Base *m = 0;
- Data::ChunkHeader *header = m_d->nonFullChunks[pos];
- if (header) {
- m = header->freeItems.nextFree();
- goto found;
- }
-
- // try to free up space, otherwise allocate
- if (!didGCRun && m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) {
- runGC();
- header = m_d->nonFullChunks[pos];
- if (header) {
- m = header->freeItems.nextFree();
- goto found;
- }
- }
-
- // no free item available, allocate a new chunk
- {
- // allocate larger chunks at a time to avoid excessive GC, but cap at maximum chunk size (2MB by default)
- uint shift = ++m_d->nChunks[pos];
- if (shift > m_d->maxShift)
- shift = m_d->maxShift;
- 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),
- OSAllocator::JSGCHeapPages);
- m_d->heapChunks.append(allocation);
- std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
-
- header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
- header->itemSize = int(size);
- header->itemStart = reinterpret_cast<char *>(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader));
- header->itemEnd = reinterpret_cast<char *>(allocation.base()) + allocation.size() - header->itemSize;
-
- header->nextNonFull = m_d->nonFullChunks[pos];
- m_d->nonFullChunks[pos] = header;
-
- Heap::Base *last = &header->freeItems;
- for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
- Heap::Base *o = reinterpret_cast<Heap::Base *>(item);
- last->setNextFree(o);
- last = o;
-
- }
- last->setNextFree(0);
- m = header->freeItems.nextFree();
- const size_t increase = (header->itemEnd - header->itemStart) / header->itemSize;
- m_d->availableItems[pos] += uint(increase);
- m_d->totalItems += int(increase);
-#ifdef V4_USE_VALGRIND
- VALGRIND_MAKE_MEM_NOACCESS(allocation.base(), allocSize);
- VALGRIND_MEMPOOL_ALLOC(this, header, sizeof(Data::ChunkHeader));
-#endif
- }
-
- found:
-#ifdef V4_USE_VALGRIND
- VALGRIND_MEMPOOL_ALLOC(this, m, size);
-#endif
- Q_V4_PROFILE_ALLOC(m_d->engine, size, Profiling::SmallItem);
-
- ++m_d->allocCount[pos];
- ++m_d->totalAlloc;
- header->freeItems.setNextFree(m->nextFree());
- if (!header->freeItems.nextFree())
- m_d->nonFullChunks[pos] = header->nextNonFull;
- return m;
-}
-
-static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
-{
- while (engine->jsStackTop > markBase) {
- Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
- }
-}
-
-void MemoryManager::mark()
-{
- Value *markBase = m_d->engine->jsStackTop;
-
- m_d->engine->markObjects();
-
- m_persistentValues->mark(m_d->engine);
-
- collectFromJSStack();
-
- // Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
- // keeps all of its children alive in JavaScript.
-
- // Do this _after_ collectFromStack to ensure that processing the weak
- // managed objects in the loop down there doesn't make then end up as leftovers
- // on the stack and thus always get collected.
- for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
- if (!(*it).isManaged())
- continue;
- if ((*it).managed()->d()->gcGetVtable() != QObjectWrapper::staticVTable())
- continue;
- QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
- if (!qobjectWrapper)
- continue;
- QObject *qobject = qobjectWrapper->object();
- if (!qobject)
- continue;
- bool keepAlive = QQmlData::keepAliveDuringGarbageCollection(qobject);
-
- if (!keepAlive) {
- if (QObject *parent = qobject->parent()) {
- while (parent->parent())
- parent = parent->parent();
-
- keepAlive = QQmlData::keepAliveDuringGarbageCollection(parent);
- }
- }
-
- if (keepAlive)
- qobjectWrapper->mark(m_d->engine);
-
- if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
- drainMarkStack(m_d->engine, markBase);
- }
-
- drainMarkStack(m_d->engine, markBase);
-}
-
-void MemoryManager::sweep(bool lastSweep)
-{
- if (m_weakValues) {
- for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
- if (Managed *m = (*it).asManaged()) {
- if (!m->markBit())
- (*it) = Primitive::undefinedValue();
- }
- }
- }
-
- if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
- for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
- if (!it.value().isNullOrUndefined())
- it = multiplyWrappedQObjects->erase(it);
- else
- ++it;
- }
- }
-
- bool *chunkIsEmpty = (bool *)alloca(m_d->heapChunks.size() * sizeof(bool));
- uint itemsInUse[MemoryManager::Data::MaxItemSize/16];
- memset(itemsInUse, 0, sizeof(itemsInUse));
- memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks));
-
- 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);
- }
-
- QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
- for (int i = 0; i < m_d->heapChunks.size(); ++i) {
- Q_ASSERT(chunkIter != m_d->heapChunks.end());
- Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(chunkIter->base());
- const size_t pos = header->itemSize >> 4;
- const size_t decrease = (header->itemEnd - header->itemStart) / header->itemSize;
-
- // 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);
-#ifdef V4_USE_VALGRIND
- VALGRIND_MEMPOOL_FREE(this, header);
-#endif
- --m_d->nChunks[pos];
- m_d->availableItems[pos] -= uint(decrease);
- m_d->totalItems -= int(decrease);
- chunkIter->deallocate();
- chunkIter = m_d->heapChunks.erase(chunkIter);
- continue;
- } else if (header->freeItems.nextFree()) {
- header->nextNonFull = m_d->nonFullChunks[pos];
- m_d->nonFullChunks[pos] = header;
- }
- ++chunkIter;
- }
-
- Data::LargeItem *i = m_d->largeItems;
- Data::LargeItem **last = &m_d->largeItems;
- while (i) {
- Heap::Base *m = i->heapObject();
- Q_ASSERT(m->inUse());
- if (m->isMarked()) {
- m->clearMarkBit();
- last = &i->next;
- i = i->next;
- continue;
- }
- if (m->gcGetVtable()->destroy)
- m->gcGetVtable()->destroy(m);
-
- *last = i->next;
- free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
- Profiling::LargeItem));
- i = *last;
- }
-
- GCDeletable *deletable = m_d->deletable;
- m_d->deletable = 0;
- while (deletable) {
- GCDeletable *next = deletable->next;
- deletable->lastCall = lastSweep;
- delete deletable;
- deletable = next;
- }
-
- // some execution contexts are allocated on the stack, make sure we clear their markBit as well
- if (!lastSweep) {
- Heap::ExecutionContext *ctx = engine()->current;
- while (ctx) {
- ctx->clearMarkBit();
- ctx = ctx->parent;
- }
- }
-}
-
-bool MemoryManager::isGCBlocked() const
-{
- return m_d->gcBlocked;
-}
-
-void MemoryManager::setGCBlocked(bool blockGC)
-{
- m_d->gcBlocked = blockGC;
-}
-
-void MemoryManager::runGC()
-{
- if (m_d->gcBlocked) {
-// qDebug() << "Not running GC.";
- return;
- }
-
- if (!m_d->gcStats) {
- mark();
- sweep();
- } else {
- const size_t totalMem = getAllocatedMem();
-
- QTime t;
- t.start();
- mark();
- int markTime = t.elapsed();
- t.restart();
- const size_t usedBefore = getUsedMem();
- int chunksBefore = m_d->heapChunks.size();
- sweep();
- const size_t usedAfter = getUsedMem();
- int sweepTime = t.elapsed();
-
- qDebug() << "========== GC ==========";
- qDebug() << "Marked object in" << markTime << "ms.";
- qDebug() << "Sweeped object in" << sweepTime << "ms.";
- qDebug() << "Allocated" << totalMem << "bytes in" << m_d->heapChunks.size() << "chunks.";
- qDebug() << "Used memory before GC:" << usedBefore;
- qDebug() << "Used memory after GC:" << usedAfter;
- qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
- qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size());
- qDebug() << "======== End GC ========";
- }
-
- memset(m_d->allocCount, 0, sizeof(m_d->allocCount));
- m_d->totalAlloc = 0;
- m_d->totalLargeItemsAllocated = 0;
-}
-
-size_t MemoryManager::getUsedMem() const
-{
- size_t usedMem = 0;
- for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
- Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
- for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
- Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
- Q_ASSERT((qintptr) item % 16 == 0);
- if (m->inUse())
- usedMem += header->itemSize;
- }
- }
- return usedMem;
-}
-
-size_t MemoryManager::getAllocatedMem() const
-{
- size_t total = 0;
- for (int i = 0; i < m_d->heapChunks.size(); ++i)
- total += m_d->heapChunks.at(i).size();
- return total;
-}
-
-size_t MemoryManager::getLargeItemsMem() const
-{
- size_t total = 0;
- for (const Data::LargeItem *i = m_d->largeItems; i != 0; i = i->next)
- total += i->size;
- return total;
-}
-
-void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta)
-{
- m_d->unmanagedHeapSize += delta;
-}
-
-MemoryManager::~MemoryManager()
-{
- delete m_persistentValues;
- delete m_weakValues;
- m_weakValues = 0;
-
- sweep(/*lastSweep*/true);
-#ifdef V4_USE_VALGRIND
- VALGRIND_DESTROY_MEMPOOL(this);
-#endif
-}
-
-ExecutionEngine *MemoryManager::engine() const
-{
- return m_d->engine;
-}
-
-void MemoryManager::dumpStats() const
-{
-#ifdef DETAILED_MM_STATS
- std::cerr << "=================" << std::endl;
- std::cerr << "Allocation stats:" << std::endl;
- std::cerr << "Requests for each chunk size:" << std::endl;
- for (int i = 0; i < m_d->allocSizeCounters.size(); ++i) {
- if (unsigned count = m_d->allocSizeCounters[i]) {
- std::cerr << "\t" << (i << 4) << " bytes chunks: " << count << std::endl;
- }
- }
-#endif // DETAILED_MM_STATS
-}
-
-void MemoryManager::registerDeletable(GCDeletable *d)
-{
- d->next = m_d->deletable;
- m_d->deletable = d;
-}
-
-#ifdef DETAILED_MM_STATS
-void MemoryManager::willAllocate(std::size_t size)
-{
- unsigned alignedSize = (size + 15) >> 4;
- QVector<unsigned> &counters = m_d->allocSizeCounters;
- if ((unsigned) counters.size() < alignedSize + 1)
- counters.resize(alignedSize + 1);
- counters[alignedSize]++;
-}
-
-#endif // DETAILED_MM_STATS
-
-void MemoryManager::collectFromJSStack() const
-{
- Value *v = m_d->engine->jsStackBase;
- Value *top = m_d->engine->jsStackTop;
- while (v < top) {
- Managed *m = v->asManaged();
- if (m && m->inUse())
- // Skip pointers to already freed objects, they are bogus as well
- m->mark(m_d->engine);
- ++v;
- }
-}
-QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h
deleted file mode 100644
index 7f6d2edba3..0000000000
--- a/src/qml/jsruntime/qv4mm_p.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QV4GC_H
-#define QV4GC_H
-
-#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
-
-//#define DETAILED_MM_STATS
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-struct GCDeletable;
-
-class Q_QML_EXPORT MemoryManager
-{
- Q_DISABLE_COPY(MemoryManager);
-
-public:
- struct Data;
-
- class GCBlocker
- {
- public:
- GCBlocker(MemoryManager *mm)
- : mm(mm)
- , wasBlocked(mm->isGCBlocked())
- {
- mm->setGCBlocked(true);
- }
-
- ~GCBlocker()
- {
- mm->setGCBlocked(wasBlocked);
- }
-
- private:
- MemoryManager *mm;
- bool wasBlocked;
- };
-
-public:
- MemoryManager(ExecutionEngine *engine);
- ~MemoryManager();
-
- // TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries).
- // Note: all occurrences of "16" in alloc/dealloc are also due to the alignment.
- static inline std::size_t align(std::size_t size)
- { return (size + 15) & ~0xf; }
-
- template<typename ManagedType>
- inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0)
- {
- size = align(size);
- Heap::Base *o = allocData(size, unmanagedSize);
- o->vtable = ManagedType::staticVTable();
- return static_cast<typename ManagedType::Data *>(o);
- }
-
- template <typename ManagedType>
- typename ManagedType::Data *alloc()
- {
- Scope scope(engine());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data();
- return t->d();
- }
-
- template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *alloc(Arg1 arg1)
- {
- 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());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data(arg1, arg2);
- return t->d();
- }
-
- template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
- typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
- {
- 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();
- }
-
- 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());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
- return t->d();
- }
-
- 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());
- 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();
- }
-
- bool isGCBlocked() const;
- void setGCBlocked(bool blockGC);
- void runGC();
-
- ExecutionEngine *engine() const;
-
- void dumpStats() const;
-
- void registerDeletable(GCDeletable *d);
-
- size_t getUsedMem() const;
- size_t getAllocatedMem() const;
- size_t getLargeItemsMem() const;
-
- void growUnmanagedHeapSizeUsage(size_t delta); // called when a JS object grows itself. Specifically: Heap::String::append
-
-protected:
- /// expects size to be aligned
- // TODO: try to inline
- Heap::Base *allocData(std::size_t size, std::size_t unmanagedSize);
-
-#ifdef DETAILED_MM_STATS
- void willAllocate(std::size_t size);
-#endif // DETAILED_MM_STATS
-
-private:
- void collectFromJSStack() const;
- void mark();
- void sweep(bool lastSweep = false);
-
-protected:
- QScopedPointer<Data> m_d;
-public:
- PersistentValueStorage *m_persistentValues;
- PersistentValueStorage *m_weakValues;
-};
-
-}
-
-QT_END_NAMESPACE
-
-#endif // QV4GC_H
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 4a1a94e872..4ae30a7f35 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -33,6 +33,7 @@
#include "qv4numberobject_p.h"
#include "qv4runtime_p.h"
+#include "qv4string_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
@@ -50,14 +51,14 @@ Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
+ReturnedValue NumberCtor::construct(const Managed *m, CallData *callData)
{
Scope scope(m->cast<NumberCtor>()->engine());
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(scope.engine->newNumberObject(dbl));
}
-ReturnedValue NumberCtor::call(Managed *, CallData *callData)
+ReturnedValue NumberCtor::call(const Managed *, CallData *callData)
{
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Encode(dbl);
@@ -67,8 +68,8 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(qSNaN()));
ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf()));
@@ -81,9 +82,9 @@ QT_WARNING_DISABLE_INTEL(239)
QT_WARNING_POP
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
+ defineDefaultProperty(engine->id_toString(), method_toString);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- defineDefaultProperty(engine->id_valueOf, method_valueOf);
+ defineDefaultProperty(engine->id_valueOf(), method_valueOf);
defineDefaultProperty(QStringLiteral("toFixed"), method_toFixed, 1);
defineDefaultProperty(QStringLiteral("toExponential"), method_toExponential);
defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision);
@@ -93,7 +94,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asReturnedValue();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return Encode(n->value());
@@ -103,7 +104,7 @@ inline double thisNumber(ExecutionContext *ctx)
{
if (ctx->thisObject().isNumber())
return ctx->thisObject().asDouble();
- NumberObject *n = ctx->thisObject().asNumberObject();
+ NumberObject *n = ctx->thisObject().as<NumberObject>();
if (!n)
return ctx->engine()->throwTypeError();
return n->value();
@@ -119,7 +120,7 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
if (ctx->argc() && !ctx->args()[0].isUndefined()) {
int radix = ctx->args()[0].toInt32();
if (radix < 2 || radix > 36)
- return ctx->engine()->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
+ return ctx->engine()->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
if (std::isnan(num)) {
@@ -197,7 +198,7 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
QString str;
if (std::isnan(v))
- str = QString::fromLatin1("NaN");
+ str = QStringLiteral("NaN");
else if (qIsInf(v))
str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity");
else if (v < 1.e21) {
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 205995701b..cc5033531e 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4NUMBEROBJECT_H
#define QV4NUMBEROBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct NumberCtor: FunctionObject
{
V4_OBJECT2(NumberCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
};
struct NumberPrototype: NumberObject
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 211fd1812e..ba29d52bc6 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -37,12 +37,14 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4lookup_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4memberdata_p.h"
#include "qv4objectiterator_p.h"
#include "qv4identifier_p.h"
+#include "qv4string_p.h"
+#include "qv4identifiertable_p.h"
#include <stdint.h>
@@ -50,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)
@@ -80,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;
@@ -115,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();
}
@@ -136,9 +152,9 @@ 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));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@@ -146,9 +162,9 @@ 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));
+ function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -165,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);
@@ -188,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)
@@ -196,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)
@@ -206,102 +230,97 @@ 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;
}
}
// Section 8.12.1
-Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs)
+void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
- return __getOwnProperty__(idx, attrs);
+ return getOwnProperty(idx, attrs, p);
uint member = internalClass()->find(name);
if (member < UINT_MAX) {
- if (attrs)
- *attrs = internalClass()->propertyData[member];
- return propertyAt(member);
+ *attrs = internalClass()->propertyData[member];
+ if (p) {
+ p->value = *propertyData(member);
+ if (attrs->isAccessor())
+ p->set = *propertyData(member + SetterOffset);
+ }
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
-Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
+void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
{
- Property *p = arrayData() ? arrayData()->getProperty(index) : 0;
- if (p) {
- if (attrs)
- *attrs = arrayData()->attributes(index);
- return p;
+ Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
+ if (pd) {
+ *attrs = arrayData()->attributes(index);
+ if (p)
+ p->copy(pd, *attrs);
+ return;
}
if (isStringObject()) {
- if (attrs)
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- return static_cast<StringObject *>(this)->getIndex(index);
+ *attrs = Attr_NotConfigurable|Attr_NotWritable;
+ if (p)
+ p->value = static_cast<StringObject *>(this)->getIndex(index);
+ return;
}
if (attrs)
*attrs = Attr_Invalid;
- return 0;
+ return;
}
// Section 8.12.2
-Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
+Value *Object::getValueOrSetter(String *name, PropertyAttributes *attrs)
{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return __getPropertyDescriptor__(idx, 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) {
- if (attrs)
- *attrs = o->arrayData->attributes(index);
- return p;
+ *attrs = o->arrayData->attributes(index);
+ return attrs->isAccessor() ? &p->set : &p->value;
}
- if (o->vtable->type == Type_StringObject) {
- Property *p = static_cast<const Heap::StringObject *>(o)->getIndex(index);
- if (p) {
- if (attrs)
- *attrs = (Attr_NotWritable|Attr_NotConfigurable);
- return p;
+ 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<Value *>(0x1);
}
}
o = o->prototype;
}
- if (attrs)
- *attrs = Attr_Invalid;
+ *attrs = Attr_Invalid;
return 0;
}
@@ -356,8 +375,7 @@ bool Object::hasOwnProperty(uint index) const
return true;
if (isStringObject()) {
- String *s = static_cast<const StringObject *>(this)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(this)->length())
return true;
}
if (!queryIndexed(index).isEmpty())
@@ -365,24 +383,24 @@ bool Object::hasOwnProperty(uint index) const
return false;
}
-ReturnedValue Object::construct(Managed *m, CallData *)
+ReturnedValue Object::construct(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::call(Managed *m, CallData *)
+ReturnedValue Object::call(const Managed *m, CallData *)
{
- return static_cast<Object *>(m)->engine()->throwTypeError();
+ return static_cast<const Object *>(m)->engine()->throwTypeError();
}
-ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGet(name, hasProperty);
+ return static_cast<const Object *>(m)->internalGet(name, hasProperty);
}
-ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty);
+ return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty);
}
void Object::put(Managed *m, String *name, const Value &value)
@@ -416,8 +434,7 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
return o->arrayData()->attributes(index);
if (o->isStringObject()) {
- String *s = static_cast<const StringObject *>(o)->d()->value.asString();
- if (index < (uint)s->d()->length())
+ if (index < static_cast<const StringObject *>(o)->length())
return (Attr_NotWritable|Attr_NotConfigurable);
}
return Attr_Invalid;
@@ -433,9 +450,9 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-ReturnedValue Object::getLookup(Managed *m, Lookup *l)
+ReturnedValue Object::getLookup(const Managed *m, Lookup *l)
{
- Object *o = static_cast<Object *>(m);
+ const Object *o = static_cast<const Object *>(m);
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -468,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);
@@ -477,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;
}
}
@@ -516,10 +533,10 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->setter = Lookup::setterGeneric;
}
-void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
if (o->arrayData()) {
@@ -531,7 +548,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
while (it->arrayNode != o->sparseEnd()) {
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
- Heap::SparseArrayData *sa = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>();
Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx);
it->arrayNode = it->arrayNode->nextNode();
PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data;
@@ -548,7 +565,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// dense arrays
while (it->arrayIndex < o->d()->arrayData->len) {
- Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>();
Value &val = sa->data(it->arrayIndex);
PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
@@ -570,13 +587,15 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
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 = 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;
}
}
@@ -585,7 +604,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name
}
// Section 8.12.3
-ReturnedValue Object::internalGet(String *name, bool *hasProperty)
+ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -600,7 +619,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
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();
@@ -611,7 +630,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
+ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const
{
Property *pd = 0;
PropertyAttributes attrs;
@@ -625,10 +644,12 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
break;
}
if (o->isStringObject()) {
- pd = static_cast<StringObject *>(o.getPointer())->getIndex(index);
- if (pd) {
+ ScopedString str(scope, static_cast<StringObject *>(o.getPointer())->getIndex(index));
+ if (str) {
attrs = (Attr_NotWritable|Attr_NotConfigurable);
- break;
+ if (hasProperty)
+ *hasProperty = true;
+ return str.asReturnedValue();
}
}
o = o->prototype();
@@ -637,7 +658,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
if (pd) {
if (hasProperty)
*hasProperty = true;
- return getValue(pd, attrs);
+ return getValue(pd->value, attrs);
}
if (hasProperty)
@@ -659,22 +680,22 @@ 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())
goto reject;
- else if (isArrayObject() && name->equals(engine()->id_length)) {
+ else if (isArrayObject() && name->equals(engine()->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
if (!ok) {
@@ -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()) {
- 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,27 +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()) {
- pd = static_cast<StringObject *>(this)->getIndex(index);
- if (pd)
+ 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())
@@ -768,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;
@@ -783,11 +801,11 @@ void Object::internalPutIndexed(uint index, const Value &value)
cont:
// Clause 5
- if (pd && attrs.isAccessor()) {
- 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;
@@ -799,7 +817,7 @@ void Object::internalPutIndexed(uint index, const Value &value)
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->current->strictMode)
engine()->throwTypeError();
}
@@ -821,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;
}
@@ -839,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;
}
@@ -854,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))
+ if (isArrayObject() && name->equals(engine->id_length())) {
+ Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()));
+ 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) {
@@ -877,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;
@@ -886,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;
@@ -903,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;
}
@@ -919,23 +936,23 @@ 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;
}
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
- Property *current = 0;
+ bool hasProperty = 0;
// Clause 1
if (arrayData()) {
- current = arrayData()->getProperty(index);
- if (!current && isStringObject())
- current = static_cast<StringObject *>(this)->getIndex(index);
+ hasProperty = arrayData()->getProperty(index);
+ if (!hasProperty && isStringObject())
+ hasProperty = (index < static_cast<StringObject *>(this)->length());
}
- if (!current) {
+ if (!hasProperty) {
// clause 3
if (!isExtensible())
goto reject;
@@ -955,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;
}
@@ -966,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);
}
@@ -1006,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);
@@ -1017,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();
}
@@ -1029,9 +1045,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
} else { // clause 10
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
- if (!p->value.isEmpty() && current->value.val != p->value.val)
+ if (!p->value.isEmpty() && current->value.rawValue() != p->value.rawValue())
goto reject;
- if (!p->set.isEmpty() && current->set.val != p->set.val)
+ if (!p->set.isEmpty() && current->set.rawValue() != p->set.rawValue())
goto reject;
}
}
@@ -1041,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;
}
@@ -1089,7 +1107,7 @@ void Object::copyArrayData(Object *other)
dd->len = other->d()->arrayData->len;
dd->offset = other->d()->arrayData->offset;
}
- memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, d()->arrayData->alloc*sizeof(Value));
+ memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, other->d()->arrayData->alloc*sizeof(Value));
}
setArrayLengthUnchecked(other->getLength());
}
@@ -1097,7 +1115,7 @@ void Object::copyArrayData(Object *other)
uint Object::getLength(const Managed *m)
{
Scope scope(static_cast<const Object *>(m)->engine());
- ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length));
+ ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length()));
return v->toUInt32();
}
@@ -1136,11 +1154,11 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
-Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+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.
@@ -1151,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(Managed *m, Lookup *l)
+ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
{
- Scope scope(static_cast<Object *>(m)->engine());
- ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(scope.engine->id_length)) {
+ Scope scope(static_cast<const Object *>(m)->engine());
+ 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;
- ArrayObject *a = static_cast<ArrayObject *>(m);
- return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
+ const ArrayObject *a = static_cast<const ArrayObject *>(m);
+ return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
}
return Object::getLookup(m, l);
}
@@ -1171,9 +1189,9 @@ ReturnedValue ArrayObject::getLookup(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 e2250b9f18..5c660f7e3f 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -33,31 +33,43 @@
#ifndef QV4_OBJECT_H
#define QV4_OBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4managed_p.h"
#include "qv4memberdata_p.h"
#include "qv4arraydata_p.h"
+#include "qv4engine_p.h"
+#include "qv4scopedvalue_p.h"
+#include "qv4value_p.h"
QT_BEGIN_NAMESPACE
+
namespace QV4 {
namespace Heap {
struct Object : Base {
- Object(ExecutionEngine *engine)
- : internalClass(engine->emptyClass),
- prototype(static_cast<Object *>(engine->objectPrototype.m))
- {
- }
- 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;
- Heap::Object *prototype;
- MemberData *memberData;
- ArrayData *arrayData;
+ Pointer<Object> prototype;
+ Pointer<MemberData> memberData;
+ Pointer<ArrayData> arrayData;
};
}
@@ -67,9 +79,9 @@ struct Object : Base {
Q_MANAGED_CHECK \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- Data *d() const { return static_cast<Data *>(m); }
+ Data *d() const { return static_cast<Data *>(m()); }
#define V4_OBJECT2(DataClass, superClass) \
private: \
@@ -80,33 +92,40 @@ struct Object : Base {
typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
- static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
V4_MANAGED_SIZE_TEST \
- QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
+ 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
{
- ManagedVTable managedVTable;
- ReturnedValue (*call)(Managed *, CallData *data);
- ReturnedValue (*construct)(Managed *, CallData *data);
- ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
- ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
+ VTable vTable;
+ ReturnedValue (*call)(const Managed *, CallData *data);
+ ReturnedValue (*construct)(const Managed *, CallData *data);
+ ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty);
+ ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
void (*put)(Managed *, String *name, const Value &value);
void (*putIndexed)(Managed *, uint index, const Value &value);
PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
- ReturnedValue (*getLookup)(Managed *m, Lookup *l);
+ ReturnedValue (*getLookup)(const Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const Value &v);
uint (*getLength)(const Managed *m);
- void (*advanceIterator)(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
#define DEFINE_OBJECT_VTABLE(classname) \
const QV4::ObjectVTable classname::static_vtbl = \
{ \
- DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \
+ DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.vTable), \
call, \
construct, \
get, \
@@ -128,31 +147,36 @@ 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); }
+ const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype; }
bool setPrototype(Object *proto);
- Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
- Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0);
+ void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
+ void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
- Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const;
- Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
+ Value *getValueOrSetter(String *name, PropertyAttributes *attrs);
+ Value *getValueOrSetter(uint index, PropertyAttributes *attrs);
bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
@@ -171,14 +195,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) {
@@ -193,10 +217,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);
@@ -273,11 +293,10 @@ public:
return false;
}
- void ensureMemberIndex(uint idx);
- inline ReturnedValue get(String *name, bool *hasProperty = 0)
+ inline ReturnedValue get(String *name, bool *hasProperty = 0) const
{ return vtable()->get(this, name, hasProperty); }
- inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
+ inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const
{ return vtable()->getIndexed(this, idx, hasProperty); }
inline void put(String *name, const Value &v)
{ vtable()->put(this, name, v); }
@@ -291,38 +310,40 @@ public:
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtable()->deleteIndexedProperty(this, index); }
- ReturnedValue getLookup(Lookup *l)
+ ReturnedValue getLookup(Lookup *l) const
{ return vtable()->getLookup(this, l); }
void setLookup(Lookup *l, const Value &v)
{ vtable()->setLookup(this, l, v); }
- void advanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+ void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
- inline ReturnedValue construct(CallData *d)
+ inline ReturnedValue construct(CallData *d) const
{ return vtable()->construct(this, d); }
- inline ReturnedValue call(CallData *d)
+ inline ReturnedValue call(CallData *d) const
{ return vtable()->call(this, d); }
protected:
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue construct(Managed *m, CallData *);
- static ReturnedValue call(Managed *m, CallData *);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue construct(const Managed *m, CallData *);
+ static ReturnedValue call(const Managed *m, CallData *);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const Value &v);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ 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);
- ReturnedValue internalGetIndexed(uint index, bool *hasProperty);
+ ReturnedValue internalGet(String *name, bool *hasProperty) const;
+ ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const;
void internalPut(String *name, const Value &value);
void internalPutIndexed(uint index, const Value &value);
bool internalDeleteProperty(String *name);
@@ -335,32 +356,18 @@ private:
namespace Heap {
struct BooleanObject : Object {
- BooleanObject(InternalClass *ic, QV4::Object *prototype)
- : Object(ic, prototype),
- b(false)
- {
- }
-
- BooleanObject(ExecutionEngine *engine, bool b)
- : Object(engine->emptyClass, engine->booleanPrototype.asObject()),
- 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.asObject()),
- value(val)
- {
- }
+ NumberObject() {}
+ NumberObject(double val)
+ : value(val)
+ {}
double value;
};
@@ -369,15 +376,11 @@ struct ArrayObject : Object {
LengthPropertyIndex = 0
};
- ArrayObject(ExecutionEngine *engine)
- : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
- { 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); }
};
}
@@ -385,6 +388,7 @@ struct ArrayObject : Object {
struct BooleanObject: Object {
V4_OBJECT2(BooleanObject, Object)
Q_MANAGED_TYPE(BooleanObject)
+ V4_PROTOTYPE(booleanPrototype)
bool value() const { return d()->b; }
@@ -393,6 +397,7 @@ struct BooleanObject: Object {
struct NumberObject: Object {
V4_OBJECT2(NumberObject, Object)
Q_MANAGED_TYPE(NumberObject)
+ V4_PROTOTYPE(numberPrototype)
double value() const { return d()->value; }
};
@@ -400,10 +405,12 @@ struct NumberObject: Object {
struct ArrayObject: Object {
V4_OBJECT2(ArrayObject, Object)
Q_MANAGED_TYPE(ArrayObject)
+ V4_INTERNALCLASS(arrayClass)
+ V4_PROTOTYPE(arrayPrototype)
void init(ExecutionEngine *engine);
- static ReturnedValue getLookup(Managed *m, Lookup *l);
+ static ReturnedValue getLookup(const Managed *m, Lookup *l);
using Object::getLength;
static uint getLength(const Managed *m);
@@ -413,7 +420,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)
@@ -436,10 +443,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);
}
@@ -451,20 +455,15 @@ 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);
}
-template<>
-inline Object *value_cast(const Value &v) {
- return v.asObject();
-}
template<>
-inline ArrayObject *value_cast(const Value &v) {
- return v.asArrayObject();
+inline const ArrayObject *Value::as() const {
+ return isManaged() && m() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : 0;
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index f36ee554a7..1413f439b1 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -35,6 +35,7 @@
#include "qv4stringobject_p.h"
#include "qv4identifier_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4string_p.h"
using namespace QV4;
@@ -50,7 +51,7 @@ ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scrat
init(o);
}
-ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
+ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags)
: engine(scope.engine)
, object(scope.alloc(1))
, current(scope.alloc(1))
@@ -62,14 +63,14 @@ ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
init(o);
}
-void ObjectIterator::init(Object *o)
+void ObjectIterator::init(const Object *o)
{
- object->m = o ? o->m : 0;
- current->m = o ? o->m : 0;
+ object->setM(o ? o->m() : 0);
+ current->setM(o ? o->m() : 0);
-#if QT_POINTER_SIZE == 4
- object->tag = QV4::Value::Managed_Type;
- current->tag = QV4::Value::Managed_Type;
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ object->setTag(QV4::Value::Managed_Type);
+ current->setTag(QV4::Value::Managed_Type);
#endif
if (object->as<ArgumentsObject>()) {
@@ -78,12 +79,12 @@ void ObjectIterator::init(Object *o)
}
}
-void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
+void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
- *name = 0;
+ name->setM(0);
*index = UINT_MAX;
- if (!object->asObject()) {
+ if (!object->as<Object>()) {
*attrs = PropertyAttributes();
return;
}
@@ -92,19 +93,19 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ScopedString n(scope);
while (1) {
- if (!current->asObject())
+ if (!current->as<Object>())
break;
while (1) {
- current->asObject()->advanceIterator(this, name, index, pd, attrs);
+ current->as<Object>()->advanceIterator(this, name, index, pd, attrs);
if (attrs->isEmpty())
break;
// check the property is not already defined earlier in the proto chain
if (current->heapObject() != object->heapObject()) {
- o = object->asObject();
+ o = object->as<Object>();
n = *name;
bool shadowed = false;
- while (o->asObject()->d() != current->heapObject()) {
+ while (o->d() != current->heapObject()) {
if ((!!n && o->hasOwnProperty(n)) ||
(*index != UINT_MAX && o->hasOwnProperty(*index))) {
shadowed = true;
@@ -119,9 +120,9 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
}
if (flags & WithProtoChain)
- current->m = current->objectValue()->prototype();
+ current->setM(current->objectValue()->prototype());
else
- current->m = (Heap::Base *)0;
+ current->setM(0);
arrayIndex = 0;
memberIndex = 0;
@@ -131,7 +132,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper
ReturnedValue ObjectIterator::nextPropertyName(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -143,17 +144,17 @@ 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();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(index);
}
ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
@@ -165,17 +166,17 @@ 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();
- assert(index < UINT_MAX);
+ Q_ASSERT(index < UINT_MAX);
return Encode(engine->newString(QString::number(index)));
}
ReturnedValue ObjectIterator::nextPropertyNameAsString()
{
- if (!object->asObject())
+ if (!object->as<Object>())
return Encode::null();
PropertyAttributes attrs;
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index a7abd2ca10..877b34c22d 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -33,6 +33,17 @@
#ifndef QV4OBJECTITERATOR_H
#define QV4OBJECTITERATOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4object_p.h"
@@ -57,9 +68,9 @@ struct Q_QML_EXPORT ObjectIterator
uint flags;
ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags);
- ObjectIterator(Scope &scope, Object *o, uint flags);
- void init(Object *o);
- void next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ ObjectIterator(Scope &scope, const Object *o, uint flags);
+ void init(const Object *o);
+ void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
ReturnedValue nextPropertyNameAsString();
@@ -67,7 +78,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 +96,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 9356ea434e..df7441ef5d 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -34,10 +34,11 @@
#include "qv4objectproto_p.h"
#include "qv4argumentsobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4runtime_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4string_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
@@ -52,14 +53,14 @@ Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
+ReturnedValue ObjectCtor::construct(const Managed *that, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(that);
ExecutionEngine *v4 = ctor->engine();
Scope scope(v4);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
ScopedObject obj(scope, v4->newObject());
- ScopedObject proto(scope, ctor->get(v4->id_prototype));
+ ScopedObject proto(scope, ctor->get(v4->id_prototype()));
if (!!proto)
obj->setPrototype(proto);
return obj.asReturnedValue();
@@ -67,9 +68,9 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
return RuntimeHelpers::toObject(scope.engine, callData->args[0]);
}
-ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
+ReturnedValue ObjectCtor::call(const Managed *m, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(m);
+ const ObjectCtor *ctor = static_cast<const ObjectCtor *>(m);
ExecutionEngine *v4 = ctor->engine();
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return v4->newObject()->asReturnedValue();
@@ -81,8 +82,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
Scope scope(v4);
ScopedObject o(scope, this);
- ctor->defineReadonlyProperty(v4->id_prototype, o);
- ctor->defineReadonlyProperty(v4->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(v4->id_prototype(), o);
+ ctor->defineReadonlyProperty(v4->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), method_getOwnPropertyDescriptor, 2);
ctor->defineDefaultProperty(QStringLiteral("getOwnPropertyNames"), method_getOwnPropertyNames, 1);
@@ -98,20 +99,20 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
ctor->defineDefaultProperty(QStringLiteral("keys"), method_keys, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(v4->id_toString, method_toString, 0);
+ defineDefaultProperty(v4->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString, 0);
- defineDefaultProperty(v4->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(v4->id_valueOf(), method_valueOf, 0);
defineDefaultProperty(QStringLiteral("hasOwnProperty"), method_hasOwnProperty, 1);
defineDefaultProperty(QStringLiteral("isPrototypeOf"), method_isPrototypeOf, 1);
defineDefaultProperty(QStringLiteral("propertyIsEnumerable"), method_propertyIsEnumerable, 1);
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);
- insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
+ p->value = BuiltinFunction::create(global, v4->id___proto__(), method_get_proto);
+ p->set = BuiltinFunction::create(global, v4->id___proto__(), method_set_proto);
+ insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
@@ -140,7 +141,8 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property *desc = O->__getOwnProperty__(name, &attrs);
+ ScopedProperty desc(scope);
+ O->getOwnProperty(name, &attrs, desc);
return fromPropertyDescriptor(scope.engine, desc, attrs);
}
@@ -163,7 +165,7 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
return ctx->engine()->throwTypeError();
ScopedObject newObject(scope, ctx->d()->engine->newObject());
- newObject->setPrototype(O->asObject());
+ newObject->setPrototype(O->as<Object>());
if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) {
ctx->d()->callData->args[0] = newObject.asReturnedValue();
@@ -220,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();
@@ -390,7 +392,7 @@ ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
} else {
ScopedObject obj(scope, RuntimeHelpers::toObject(scope.engine, ctx->thisObject()));
QString className = obj->className();
- return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("[object %1]").arg(className))->asReturnedValue();
}
}
@@ -400,7 +402,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
ScopedObject o(scope, ctx->thisObject().toObject(scope.engine));
if (!o)
return Encode::undefined();
- ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString));
+ ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString()));
if (!f)
return ctx->engine()->throwTypeError();
ScopedCallData callData(scope);
@@ -462,7 +464,7 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
PropertyAttributes attrs;
- o->__getOwnProperty__(p, &attrs);
+ o->getOwnProperty(p, &attrs);
return Encode(attrs.isEnumerable());
}
@@ -484,7 +486,7 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -512,7 +514,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
if (!o) {
if (!ctx->thisObject().isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject();
+ o = ctx->d()->engine->globalObject;
}
ScopedProperty pd(scope);
@@ -525,7 +527,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->thisObject().asObject());
+ ScopedObject o(scope, ctx->thisObject().as<Object>());
if (!o)
return ctx->engine()->throwTypeError();
@@ -572,15 +574,15 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(engine->id_enumerable))
- attrs->setEnumerable((tmp = o->get(engine->id_enumerable))->toBoolean());
+ if (o->hasProperty(engine->id_enumerable()))
+ attrs->setEnumerable((tmp = o->get(engine->id_enumerable()))->toBoolean());
- if (o->hasProperty(engine->id_configurable))
- attrs->setConfigurable((tmp = o->get(engine->id_configurable))->toBoolean());
+ if (o->hasProperty(engine->id_configurable()))
+ attrs->setConfigurable((tmp = o->get(engine->id_configurable()))->toBoolean());
- if (o->hasProperty(engine->id_get)) {
- ScopedValue get(scope, o->get(engine->id_get));
- FunctionObject *f = get->asFunctionObject();
+ if (o->hasProperty(engine->id_get())) {
+ ScopedValue get(scope, o->get(engine->id_get()));
+ FunctionObject *f = get->as<FunctionObject>();
if (f || get->isUndefined()) {
desc->value = get;
} else {
@@ -590,9 +592,9 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_set)) {
- ScopedValue set(scope, o->get(engine->id_set));
- FunctionObject *f = set->asFunctionObject();
+ if (o->hasProperty(engine->id_set())) {
+ ScopedValue set(scope, o->get(engine->id_set()));
+ FunctionObject *f = set->as<FunctionObject>();
if (f || set->isUndefined()) {
desc->set = set;
} else {
@@ -602,22 +604,22 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(engine->id_writable)) {
+ if (o->hasProperty(engine->id_writable())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- attrs->setWritable((tmp = o->get(engine->id_writable))->toBoolean());
+ attrs->setWritable((tmp = o->get(engine->id_writable()))->toBoolean());
// writable forces it to be a data descriptor
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(engine->id_value)) {
+ if (o->hasProperty(engine->id_value())) {
if (attrs->isAccessor()) {
engine->throwTypeError();
return;
}
- desc->value = o->get(engine->id_value);
+ desc->value = o->get(engine->id_value());
attrs->setType(PropertyAttributes::Data);
}
@@ -628,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/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 4e96681017..ec829e4bd2 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -33,6 +33,17 @@
#ifndef QV4ECMAOBJECTS_P_H
#define QV4ECMAOBJECTS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -53,8 +64,8 @@ struct ObjectCtor: FunctionObject
{
V4_OBJECT2(ObjectCtor, FunctionObject)
- static ReturnedValue construct(Managed *that, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *that, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct ObjectPrototype: Object
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 88dc1946b8..4a0f84b685 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4persistent_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4object_p.h"
#include "PageAllocation.h"
@@ -78,11 +78,11 @@ Page *allocatePage(PersistentValueStorage *storage)
if (p->header.next)
p->header.next->header.prev = &p->header.next;
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
- p->values[i].tag = QV4::Value::Empty_Type;
- p->values[i].int_32 = i + 1;
+ p->values[i].setTag(QV4::Value::Empty_Type);
+ p->values[i].setInt_32(i + 1);
}
- p->values[kEntriesPerPage - 1].tag = QV4::Value::Empty_Type;
- p->values[kEntriesPerPage - 1].int_32 = -1;
+ p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type);
+ p->values[kEntriesPerPage - 1].setInt_32(-1);
storage->firstPage = p;
@@ -93,15 +93,57 @@ Page *allocatePage(PersistentValueStorage *storage)
}
+PersistentValueStorage::Iterator::Iterator(void *p, int idx)
+ : p(p), index(idx)
+{
+ Page *page = static_cast<Page *>(p);
+ if (page)
+ ++page->header.refCount;
+}
+
+PersistentValueStorage::Iterator::Iterator(const PersistentValueStorage::Iterator &o)
+ : p(o.p), index(o.index)
+{
+ Page *page = static_cast<Page *>(p);
+ if (page)
+ ++page->header.refCount;
+}
+
+PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator=(const PersistentValueStorage::Iterator &o)
+{
+ Page *page = static_cast<Page *>(p);
+ if (page && !--page->header.refCount)
+ freePage(p);
+ p = o.p;
+ index = o.index;
+ page = static_cast<Page *>(p);
+ if (page)
+ ++page->header.refCount;
+
+ return *this;
+}
+
+PersistentValueStorage::Iterator::~Iterator()
+{
+ Page *page = static_cast<Page *>(p);
+ if (page && !--page->header.refCount)
+ freePage(page);
+}
+
PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++() {
while (p) {
while (index < kEntriesPerPage - 1) {
++index;
- if (static_cast<Page *>(p)->values[index].tag != QV4::Value::Empty_Type)
+ if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type)
return *this;
}
index = -1;
- p = static_cast<Page *>(p)->header.next;
+ Page *next = static_cast<Page *>(p)->header.next;
+ if (!--static_cast<Page *>(p)->header.refCount)
+ freePage(p);
+ p = next;
+ if (next)
+ ++next->header.refCount;
}
index = 0;
return *this;
@@ -147,10 +189,10 @@ Value *PersistentValueStorage::allocate()
p = allocatePage(this);
Value *v = p->values + p->header.freeList;
- p->header.freeList = v->int_32;
+ p->header.freeList = v->int_32();
++p->header.refCount;
- v->val = Encode::undefined();
+ v->setRawValue(Encode::undefined());
return v;
}
@@ -162,24 +204,19 @@ void PersistentValueStorage::free(Value *v)
Page *p = getPage(v);
- v->tag = QV4::Value::Empty_Type;
- v->int_32 = p->header.freeList;
+ v->setTag(QV4::Value::Empty_Type);
+ v->setInt_32(p->header.freeList);
p->header.freeList = v - p->values;
- if (!--p->header.refCount) {
- if (p->header.prev)
- *p->header.prev = p->header.next;
- if (p->header.next)
- p->header.next->header.prev = p->header.prev;
- p->header.alloc.deallocate();
- }
+ if (!--p->header.refCount)
+ freePage(p);
}
static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->gcGetVtable()->markObjects);
- h->gcGetVtable()->markObjects(h, engine);
+ Q_ASSERT (h->vtable()->markObjects);
+ h->vtable()->markObjects(h, engine);
}
}
@@ -190,7 +227,7 @@ void PersistentValueStorage::mark(ExecutionEngine *e)
Page *p = static_cast<Page *>(firstPage);
while (p) {
for (int i = 0; i < kEntriesPerPage; ++i) {
- if (Managed *m = p->values[i].asManaged())
+ if (Managed *m = p->values[i].as<Managed>())
m->mark(e);
}
drainMarkStack(e, markBase);
@@ -204,6 +241,16 @@ ExecutionEngine *PersistentValueStorage::getEngine(Value *v)
return getPage(v)->header.engine;
}
+void PersistentValueStorage::freePage(void *page)
+{
+ Page *p = static_cast<Page *>(page);
+ if (p->header.prev)
+ *p->header.prev = p->header.next;
+ if (p->header.next)
+ p->header.next->header.prev = p->header.prev;
+ p->header.alloc.deallocate();
+}
+
PersistentValue::PersistentValue(const PersistentValue &other)
: val(0)
@@ -312,6 +359,12 @@ WeakValue::WeakValue(const WeakValue &other)
}
}
+WeakValue::WeakValue(ExecutionEngine *engine, const Value &value)
+{
+ val = engine->memoryManager->m_weakValues->allocate();
+ *val = value;
+}
+
WeakValue &WeakValue::operator=(const WeakValue &other)
{
if (!val) {
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 7cac2ed95f..80b4ecdea8 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -33,7 +33,19 @@
#ifndef QV4PERSISTENT_H
#define QV4PERSISTENT_H
-#include "qv4value_inl_p.h"
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qv4value_p.h"
+#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
@@ -50,8 +62,10 @@ struct Q_QML_EXPORT PersistentValueStorage
void mark(ExecutionEngine *e);
struct Iterator {
- Q_DECL_CONSTEXPR Iterator(void *p, int idx)
- : p(p), index(idx) {}
+ Iterator(void *p, int idx);
+ Iterator(const Iterator &o);
+ Iterator & operator=(const Iterator &o);
+ ~Iterator();
void *p;
int index;
Iterator &operator++();
@@ -67,6 +81,8 @@ struct Q_QML_EXPORT PersistentValueStorage
ExecutionEngine *engine;
void *firstPage;
+private:
+ static void freePage(void *page);
};
class Q_QML_EXPORT PersistentValue
@@ -96,7 +112,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template<typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
@@ -122,6 +144,7 @@ class Q_QML_EXPORT WeakValue
public:
WeakValue() : val(0) {}
WeakValue(const WeakValue &other);
+ WeakValue(ExecutionEngine *engine, const Value &value);
WeakValue &operator=(const WeakValue &other);
~WeakValue();
@@ -138,7 +161,13 @@ public:
Managed *asManaged() const {
if (!val)
return 0;
- return val->asManaged();
+ return val->as<Managed>();
+ }
+ template <typename T>
+ T *as() const {
+ if (!val)
+ return 0;
+ return val->as<T>();
}
ExecutionEngine *engine() const {
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index a7019d0558..b62f367601 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -32,12 +32,13 @@
****************************************************************************/
#include "qv4profiling_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
+#include <private/qv4string_p.h>
QT_BEGIN_NAMESPACE
-using namespace QV4;
-using namespace QV4::Profiling;
+namespace QV4 {
+namespace Profiling {
FunctionCallProperties FunctionCall::resolve() const
{
@@ -55,42 +56,43 @@ FunctionCallProperties FunctionCall::resolve() const
Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
{
- static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
- static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >();
- Q_UNUSED(metatype);
- Q_UNUSED(metatype2);
+ static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >();
+ static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >();
+ Q_UNUSED(meta);
+ Q_UNUSED(meta2);
m_timer.start();
}
-struct FunctionCallComparator {
- bool operator()(const FunctionCallProperties &p1, const FunctionCallProperties &p2)
- { return p1.start < p2.start; }
-};
-
void Profiler::stopProfiling()
{
featuresEnabled = 0;
reportData();
}
+bool operator<(const FunctionCall &call1, const FunctionCall &call2)
+{
+ return call1.m_start < call2.m_start ||
+ (call1.m_start == call2.m_start && (call1.m_end < call2.m_end ||
+ (call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
+}
+
void Profiler::reportData()
{
- QList<FunctionCallProperties> resolved;
+ std::sort(m_data.begin(), m_data.end());
+ QVector<FunctionCallProperties> resolved;
resolved.reserve(m_data.size());
- FunctionCallComparator comp;
- foreach (const FunctionCall &call, m_data) {
- FunctionCallProperties props = call.resolve();
- resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props);
- }
+
+ foreach (const FunctionCall &call, m_data)
+ resolved.append(call.resolve());
+
emit dataReady(resolved, m_memory_data);
+ m_data.clear();
+ m_memory_data.clear();
}
void Profiler::startProfiling(quint64 features)
{
if (featuresEnabled == 0) {
- m_data.clear();
- m_memory_data.clear();
-
if (features & (1 << FeatureMemoryAllocation)) {
qint64 timestamp = m_timer.nsecsElapsed();
MemoryAllocationProperties heap = {timestamp,
@@ -111,4 +113,7 @@ void Profiler::startProfiling(quint64 features)
}
}
+} // namespace Profiling
+} // namespace QV4
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index c3441eaacd..6c54fc9bbd 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -34,6 +34,17 @@
#ifndef QV4PROFILING_H
#define QV4PROFILING_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4function_p.h"
@@ -104,6 +115,7 @@ public:
FunctionCallProperties resolve() const;
private:
+ friend bool operator<(const FunctionCall &call1, const FunctionCall &call2);
Function *m_function;
qint64 m_start;
@@ -155,14 +167,14 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &,
- const QList<QV4::Profiling::MemoryAllocationProperties> &);
+ void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
QV4::ExecutionEngine *m_engine;
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
- QList<MemoryAllocationProperties> m_memory_data;
+ QVector<MemoryAllocationProperties> m_memory_data;
friend class FunctionCallProfiler;
};
@@ -202,7 +214,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>)
-Q_DECLARE_METATYPE(QList<QV4::Profiling::MemoryAllocationProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
+Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 1b55abd1f7..8ddb4cf6f7 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -33,9 +33,19 @@
#ifndef QV4PROPERTYDESCRIPTOR_H
#define QV4PROPERTYDESCRIPTOR_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4value_p.h"
-#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -73,8 +83,8 @@ struct Property {
inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; }
inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
- inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
- inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); }
+ inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
+ inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : 0); }
void copy(const Property *other, PropertyAttributes attrs) {
value = other->value;
@@ -85,12 +95,12 @@ struct Property {
explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); }
Property(FunctionObject *getter, FunctionObject *setter) {
- value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter));
- set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter));
+ value = reinterpret_cast<Managed *>(getter);
+ set = reinterpret_cast<Managed *>(setter);
}
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
- value.m = reinterpret_cast<Heap::Base *>(getter);
- set.m = reinterpret_cast<Heap::Base *>(setter);
+ value.setM(reinterpret_cast<Heap::Base *>(getter));
+ set.setM(reinterpret_cast<Heap::Base *>(setter));
}
Property &operator=(Value v) { value = v; return *this; }
private:
diff --git a/src/qml/jsruntime/qv4qmlextensions.cpp b/src/qml/jsruntime/qv4qmlextensions.cpp
deleted file mode 100644
index c1c4e0ec78..0000000000
--- a/src/qml/jsruntime/qv4qmlextensions.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4qmlextensions_p.h"
-#include "qv4object_p.h"
-
-using namespace QV4;
-
-void QmlExtensions::markObjects(ExecutionEngine *e)
-{
- if (valueTypeWrapperPrototype)
- valueTypeWrapperPrototype->mark(e);
-}
diff --git a/src/qml/jsruntime/qv4qmlextensions_p.h b/src/qml/jsruntime/qv4qmlextensions_p.h
deleted file mode 100644
index e4b9f75298..0000000000
--- a/src/qml/jsruntime/qv4qmlextensions_p.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QV4QMLEXTENSIONS_P_H
-#define QV4QMLEXTENSIONS_P_H
-
-#include <qtqmlglobal.h>
-#include <qv4global_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-struct Q_QML_EXPORT QmlExtensions
-{
- QmlExtensions()
- : valueTypeWrapperPrototype(0)
- {}
-
- Heap::Object *valueTypeWrapperPrototype;
-
- void markObjects(ExecutionEngine *e);
-};
-
-} // namespace QV4
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 0a1aa56aab..8f471132b7 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -55,6 +55,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4dateobject_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4mm_p.h>
#include <private/qqmlscriptstring_p.h>
@@ -92,7 +93,7 @@ static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
static QPair<QObject *, int> extractQtSignal(const Value &value)
{
if (value.isObject()) {
- QV4::ExecutionEngine *v4 = value.asObject()->engine();
+ QV4::ExecutionEngine *v4 = value.as<Object>()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope, value);
if (function)
@@ -227,16 +228,15 @@ 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)
{
}
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
{
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
- engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
+ engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
@@ -254,8 +254,8 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
return result;
}
-ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
- bool *hasProperty, bool includeImports)
+ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
+ bool *hasProperty, bool includeImports) const
{
if (QQmlData::wasDeleted(d()->object)) {
if (hasProperty)
@@ -263,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()) {
@@ -291,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");
@@ -317,14 +315,11 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
if (hasProperty)
*hasProperty = true;
- ScopedContext ctx(scope, scope.engine->currentContext());
- return getProperty(d()->object, ctx, result);
+ return getProperty(v4, d()->object, result);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QV4::Scope scope(ctx);
-
QQmlData::flushPendingBinding(object, property->coreIndex);
if (property->isFunction() && !property->isVarProperty()) {
@@ -333,25 +328,19 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- QV4::ScopedObject qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
- ScopedContext global(scope, scope.engine->rootContext());
- return QV4::QObjectMethod::create(global, object, property->coreIndex, qmlcontextobject);
+ 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>(ctx->d()->engine, object, property->coreIndex));
-
- QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->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;
@@ -360,37 +349,38 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine, object, *property, nptr));
+ Scope scope(engine);
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
- if (n)
- ep->captureProperty(n);
+ if (n && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(n);
} else {
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
}
}
return rv->asReturnedValue();
}
- if (captureRequired && ep && !property->isConstant())
- ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+ if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
+ ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(engine, object, *property, 0);
}
}
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,23 +420,21 @@ bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qm
return false;
}
- Scope scope(engine);
- ScopedContext ctx(scope, engine->currentContext());
- setProperty(object, ctx, result, value);
+ setProperty(engine, object, result, value);
return true;
}
-void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value)
{
if (!property->isWritable() && !property->isQList()) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
property->name(object) + QLatin1Char('\"');
- ctx->engine()->throwTypeError(error);
+ engine->throwTypeError(error);
return;
}
QQmlBinding *newBinding = 0;
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
@@ -460,25 +445,25 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
newBinding = new QQmlBinding(value, object, callingQmlContext);
- newBinding->setTarget(object, *property, callingQmlContext);
+ newBinding->setTarget(object, *property);
}
}
- QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
- if (oldBinding)
- oldBinding->destroy();
+ if (newBinding)
+ QQmlPropertyPrivate::setBinding(newBinding);
+ else
+ QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
@@ -505,16 +490,16 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else if (value.isUndefined() && property->propType == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
- PROPERTY_STORE(QJSValue, QJSValue(ctx->d()->engine, value.asReturnedValue()));
+ PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
} else if (value.isUndefined() && property->propType != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(property->propType))
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
- } else if (value.asFunctionObject()) {
+ } else if (value.as<FunctionObject>()) {
// this is handled by the binding creation above
} else if (property->propType == QMetaType::Int && value.isNumber()) {
PROPERTY_STORE(int, value.asDouble());
@@ -543,11 +528,11 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else {
QVariant v;
if (property->isQList())
- v = ctx->d()->engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = ctx->d()->engine->toVariant(value, property->propType);
+ v = scope.engine->toVariant(value, property->propType);
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
+ QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = 0;
if (v.userType() == QVariant::Invalid) valueType = "null";
@@ -561,7 +546,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QLatin1String(valueType) +
QLatin1String(" to ") +
QLatin1String(targetTypeName);
- ctx->engine()->throwError(error);
+ scope.engine->throwError(error);
return;
}
}
@@ -634,7 +619,7 @@ void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine)
engine->m_multiplyWrappedQObjects->mark(object, engine);
}
-ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired)
{
if (QQmlData::wasDeleted(object))
return QV4::Encode::null();
@@ -646,14 +631,19 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(object, ctx, property, captureRequired);
+ return getProperty(engine, object, property, captureRequired);
+}
+
+void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value)
+{
+ setProperty(engine, d()->object, propertyIndex, value);
}
-void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value)
+void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
{
- if (QQmlData::wasDeleted(d()->object))
+ if (QQmlData::wasDeleted(object))
return;
- QQmlData *ddata = QQmlData::get(d()->object, /*create*/false);
+ QQmlData *ddata = QQmlData::get(object, /*create*/false);
if (!ddata)
return;
@@ -661,14 +651,14 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return setProperty(d()->object, ctx, property, value);
+ return setProperty(engine, object, property, value);
}
bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QObjectWrapper>());
QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a);
- QV4::Object *o = b->asObject();
+ QV4::Object *o = b->as<Object>();
if (o) {
if (QV4::QmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QmlTypeWrapper>())
return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
@@ -681,13 +671,13 @@ 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(Managed *m, String *name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty)
{
- QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(that->engine());
+ const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ QQmlContextData *qmlContext = that->engine()->callingQmlContext();
return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
@@ -699,7 +689,7 @@ void QObjectWrapper::put(Managed *m, String *name, const Value &value)
if (v4->hasException || QQmlData::wasDeleted(that->d()->object))
return;
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
+ QQmlContextData *qmlContext = v4->callingQmlContext();
if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object);
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
@@ -718,23 +708,23 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(engine);
+ QQmlContextData *qmlContext = engine->callingQmlContext();
QQmlPropertyData local;
if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local)
- || name->equals(engine->id_destroy) || name->equals(engine->id_toString))
+ || name->equals(engine->id_destroy()) || name->equals(engine->id_toString()))
return QV4::Attr_Data;
else
return QV4::Object::query(m, name);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
@@ -745,10 +735,9 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- // #### GC
Scope scope(that->engine());
ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
- *name = propName->d();
+ name->setM(propName->d());
++it->arrayIndex;
*attributes = QV4::Attr_Data;
p->value = that->get(propName);
@@ -761,10 +750,9 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::Strin
++it->arrayIndex;
if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
- // #### GC
Scope scope(that->engine());
ScopedString methodName(scope, that->engine()->newString(QString::fromUtf8(method.name())));
- *name = methodName->d();
+ name->setM(methodName->d());
*attributes = QV4::Attr_Data;
p->value = that->get(methodName);
return;
@@ -811,7 +799,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ScopedFunctionObject f(scope, This->function.value());
QV4::ScopedCallData callData(scope, argCount);
- callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject()->asReturnedValue() : This->thisObject.value();
+ callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
@@ -826,7 +814,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty()) {
QV4::ScopedString name(scope, f->name());
- error.setDescription(QString::fromLatin1("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
+ error.setDescription(QStringLiteral("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
}
if (QQmlEngine *qmlEngine = v4->qmlEngine()) {
QQmlEnginePrivate::get(qmlEngine)->warning(error);
@@ -1028,56 +1016,35 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
QV4::Object::markObjects(that, e);
}
-namespace {
- struct QObjectDeleter : public QV4::GCDeletable
- {
- QObjectDeleter(QObject *o)
- : m_objectToDelete(o)
- {}
- ~QObjectDeleter()
- {
- QQmlData *ddata = QQmlData::get(m_objectToDelete, false);
- if (ddata && ddata->ownContext && ddata->context)
- ddata->context->emitDestruction();
- // This object is notionally destroyed now
- ddata->isQueuedForDeletion = true;
- if (lastCall)
- delete m_objectToDelete;
- else
- m_objectToDelete->deleteLater();
- }
-
- QObject *m_objectToDelete;
- };
-}
-
-void QObjectWrapper::destroy(Heap::Base *that)
+void QObjectWrapper::destroyObject(bool lastCall)
{
- Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper*>(that);
- QPointer<QObject> object = This->object;
- ExecutionEngine *engine = This->internalClass->engine;
- This->~Data();
- This = 0;
- if (!object)
- return;
-
- QQmlData *ddata = QQmlData::get(object, false);
- if (!ddata)
- return;
-
- if (object->parent() || ddata->indestructible)
- return;
+ Heap::QObjectWrapper *h = d();
+ if (!h->internalClass)
+ return; // destroyObject already got called
+
+ if (h->object) {
+ QQmlData *ddata = QQmlData::get(h->object, false);
+ if (ddata) {
+ 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 h->object;
+ else
+ h->object->deleteLater();
+ }
+ }
+ }
- QObjectDeleter *deleter = new QObjectDeleter(object);
- engine->memoryManager->registerDeletable(deleter);
+ h->internalClass = 0;
+ h->~Data();
}
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,
@@ -1229,7 +1196,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asDateObject()) {
+ } else if (actual.as<DateObject>()) {
switch (conversionType) {
case QMetaType::QDateTime:
return 0;
@@ -1247,7 +1214,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
- } else if (actual.asArrayObject()) {
+ } else if (actual.as<ArrayObject>()) {
switch (conversionType) {
case QMetaType::QJsonArray:
return 3;
@@ -1276,7 +1243,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
return 10;
}
}
- } else if (QV4::Object *obj = actual.asObject()) {
+ } else if (const Object *obj = actual.as<Object>()) {
if (obj->as<QV4::VariantObject>()) {
if (conversionType == qMetaTypeId<QVariant>())
return 0;
@@ -1379,7 +1346,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (returnType == QMetaType::UnknownType) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method return type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1392,7 +1359,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
- QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
+ QString error = QStringLiteral("Unknown method parameter type: %1").arg(typeName);
return engine->throwError(error);
}
@@ -1606,9 +1573,9 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
- else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
+ else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
@@ -1630,7 +1597,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
}
} else {
QObject *o = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
o = qobjectWrapper->object();
qlistPtr->append(o);
}
@@ -1739,29 +1706,26 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
}
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal)
+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()->qmlGlobal = qmlGlobal;
- method->d()->valueTypeWrapper = Primitive::undefinedValue();
return method.asReturnedValue();
}
-ReturnedValue QObjectMethod::create(ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal)
+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()->qmlGlobal = qmlGlobal;
- method->d()->valueTypeWrapper = valueType;
+ method->d()->valueTypeWrapper = valueType->d();
return method.asReturnedValue();
}
@@ -1777,7 +1741,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject()
return object->metaObject();
}
-QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
+QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const
{
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
@@ -1803,7 +1767,7 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
return ctx->d()->engine->newString(result)->asReturnedValue();
}
-QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
+QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const
{
if (!d()->object)
return Encode::undefined();
@@ -1822,16 +1786,16 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
return Encode::undefined();
}
-ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
+ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
{
- QObjectMethod *This = static_cast<QObjectMethod*>(m);
+ const QObjectMethod *This = static_cast<const QObjectMethod*>(m);
return This->callInternal(callData);
}
-ReturnedValue QObjectMethod::callInternal(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)
@@ -1839,11 +1803,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
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;
@@ -1875,12 +1838,9 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
}
if (method.isV4Function()) {
+ Scope scope(v4);
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
-
- QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal);
- QQmlV4Function func(callData, rv, qmlGlobal,
- QmlContextWrapper::getContext(qmlGlobal),
- scope.engine);
+ QQmlV4Function func(callData, rv, v4);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
@@ -1890,32 +1850,46 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
}
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->qmlGlobal.mark(e);
- 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 24e8b29e08..1126013806 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -54,7 +54,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qintrusivelist_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE
@@ -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;
};
@@ -79,15 +81,14 @@ struct QObjectMethod : FunctionObject {
QPointer<QObject> object;
QQmlRefPointer<QQmlPropertyCache> propertyCache;
int index;
- Value qmlGlobal;
- 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;
};
@@ -104,7 +105,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object.data(); }
- ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
+ ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false) const;
static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
@@ -114,26 +115,27 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
using Object::get;
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired);
- void setProperty(ExecutionContext *ctx, int propertyIndex, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, bool captureRequired);
+ static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value);
+ void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
+
+ void destroyObject(bool lastCall);
protected:
static bool isEqualTo(Managed *that, Managed *o);
-private:
- static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
- static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const Value &value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired = true);
+ static void setProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, const Value &value);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
- static void destroy(Heap::Base *that);
static ReturnedValue method_connect(CallContext *ctx);
static ReturnedValue method_disconnect(CallContext *ctx);
@@ -148,18 +150,18 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
enum { DestroyMethod = -1, ToStringMethod = -2 };
- static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal = Primitive::undefinedValue());
- static ReturnedValue create(QV4::ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue());
+ static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index);
+ static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index);
int methodIndex() const { return d()->index; }
QObject *object() const { return d()->object.data(); }
- QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx);
- QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
+ QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const;
+ QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const;
- static ReturnedValue call(Managed *, CallData *callData);
+ static ReturnedValue call(const Managed *, CallData *callData);
- ReturnedValue callInternal(CallData *callData);
+ ReturnedValue callInternal(CallData *callData) const;
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
};
@@ -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/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 8e18a5fbdd..31fee534ad 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -34,16 +34,16 @@
#include "qv4regexp_p.h"
#include "qv4engine_p.h"
#include "qv4scopedvalue_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
using namespace QV4;
RegExpCache::~RegExpCache()
{
- for (RegExpCache::Iterator it = begin(), e = end();
- it != e; ++it)
- it.value()->cache = 0;
- clear();
+ for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) {
+ if (RegExp *re = it.value().as<RegExp>())
+ re->d()->cache = 0;
+ }
}
DEFINE_MANAGED_VTABLE(RegExp);
@@ -68,19 +68,18 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
RegExpCacheKey key(pattern, ignoreCase, multiline);
RegExpCache *cache = engine->regExpCache;
- if (cache) {
- if (Heap::RegExp *result = cache->value(key))
- return result;
- }
+ if (!cache)
+ cache = engine->regExpCache = new RegExpCache;
+
+ QV4::WeakValue &cachedValue = (*cache)[key];
+ if (QV4::RegExp *result = cachedValue.as<RegExp>())
+ return result->d();
Scope scope(engine);
Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline));
- if (!cache)
- cache = engine->regExpCache = new RegExpCache;
-
result->d()->cache = cache;
- cache->insert(key, result->d());
+ cachedValue.set(engine, result);
return result->d();
}
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 819e31e5f1..928362a995 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -33,6 +33,17 @@
#ifndef QV4REGEXP_H
#define QV4REGEXP_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QString>
#include <QVector>
@@ -133,8 +144,7 @@ inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
{ return qHash(key.pattern, seed); }
-// ### GC
-class RegExpCache : public QHash<RegExpCacheKey, Heap::RegExp*>
+class RegExpCache : public QHash<RegExpCacheKey, WeakValue>
{
public:
~RegExpCache();
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index f6e88e62b7..1839ff17ab 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -37,7 +37,7 @@
#include "qv4objectproto_p.h"
#include "qv4regexp_p.h"
#include "qv4stringobject_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -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.asObject())
- , 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.asObject())
+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);
+ Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
+ return propertyData(0);
}
// Converts a JS RegExp to a QRegExp.
@@ -231,25 +221,24 @@ Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope)
void Heap::RegExpCtor::clearLastMatch()
{
lastMatch = Primitive::nullValue();
- lastInput = internalClass->engine->id_empty;
+ lastInput = internalClass->engine->id_empty()->d();
lastMatchStart = 0;
lastMatchEnd = 0;
}
-ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
- ScopedContext ctx(scope, scope.engine->currentContext());
+ Scope scope(static_cast<const Object *>(m)->engine());
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,19 +263,19 @@ ReturnedValue RegExpCtor::construct(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(Managed *that, CallData *callData)
+ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData)
{
if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
if (callData->argc == 1 || callData->args[1].isUndefined())
@@ -300,7 +289,7 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
{
RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
This->lastMatch.mark(e);
- This->lastInput.mark(e);
+ This->lastInput->mark(e);
FunctionObject::markObjects(that, e);
}
@@ -310,8 +299,8 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
ScopedObject o(scope);
ScopedObject ctor(scope, constructor);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(2));
// Properties deprecated in the spec but required by "the web" :(
ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
@@ -337,7 +326,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
- defineDefaultProperty(engine->id_toString, method_toString, 0);
+ defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
}
@@ -354,25 +343,25 @@ 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();
}
uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- r->lastIndexProperty()->value = Primitive::fromInt32(0);
+ *r->lastIndexProperty() = Primitive::fromInt32(0);
return Encode::null();
}
// fill in result data
- ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject()));
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype()));
int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
@@ -383,17 +372,17 @@ 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;
- dd->lastInput = arg->stringValue();
+ dd->lastInput = arg->stringValue()->d();
dd->lastMatchStart = matchOffsets[0];
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- r->lastIndexProperty()->value = Primitive::fromInt32(matchOffsets[1]);
+ *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
return array.asReturnedValue();
}
@@ -425,7 +414,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
ScopedCallData callData(scope, ctx->argc());
memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value));
- Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData));
+ Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor()->as<FunctionObject>()->construct(callData));
r->d()->value = re->value();
r->d()->global = re->global();
@@ -436,7 +425,7 @@ template <int index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -446,7 +435,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
return ctx->d()->engine->newString()->asReturnedValue();
@@ -455,13 +444,13 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
{
- return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue();
+ return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue();
}
@@ -469,7 +458,7 @@ ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index f5f255faf5..81ea9cf14b 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4REGEXPOBJECT_H
#define QV4REGEXPOBJECT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4runtime_p.h"
#include "qv4engine_p.h"
#include "qv4context_p.h"
@@ -57,33 +68,30 @@ 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);
- RegExp *value;
+ Pointer<RegExp> value;
bool global;
};
struct RegExpCtor : FunctionObject {
RegExpCtor(QV4::ExecutionContext *scope);
Value lastMatch;
- StringValue lastInput;
+ Pointer<String> lastInput;
int lastMatchStart;
int lastMatchEnd;
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 +101,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 +113,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;
@@ -117,19 +130,17 @@ struct RegExpCtor: FunctionObject
V4_OBJECT2(RegExpCtor, FunctionObject)
Value lastMatch() { return d()->lastMatch; }
- StringValue lastInput() { return d()->lastInput; }
+ Heap::String *lastInput() { return d()->lastInput; }
int lastMatchStart() { return d()->lastMatchStart; }
int lastMatchEnd() { return d()->lastMatchEnd; }
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
{
- V4_OBJECT2(RegExpPrototype, RegExpObject)
-
void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_exec(CallContext *ctx);
@@ -145,11 +156,6 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_get_rightContext(CallContext *ctx);
};
-inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
- : RegExpObject(e->emptyClass, e->objectPrototype.asObject())
-{
-}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index b66e917b87..a988313f5f 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -40,12 +40,15 @@
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4dateobject_p.h"
#include "qv4lookup_p.h"
#include "qv4function_p.h"
#include "private/qlocale_tools_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmltypewrapper_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include "qv4qobjectwrapper_p.h"
#include <private/qv8engine_p.h>
#endif
@@ -265,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)
@@ -289,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);
}
@@ -305,22 +307,21 @@ 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)
{
Scope scope(engine);
- ScopedFunctionObject f(scope, right.asFunctionObject());
+ ScopedFunctionObject f(scope, right.as<FunctionObject>());
if (!f)
return engine->throwTypeError();
if (f->isBoundFunction())
f = static_cast<BoundFunction *>(f.getPointer())->target();
- ScopedObject v(scope, left.asObject());
+ ScopedObject v(scope, left.as<Object>());
if (!v)
return Encode(false);
@@ -380,10 +381,10 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n
return engine->newString(qstr);
}
-ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
+ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint)
{
if (typeHint == PREFERREDTYPE_HINT) {
- if (object->asDateObject())
+ if (object->as<DateObject>())
typeHint = STRING_HINT;
else
typeHint = NUMBER_HINT;
@@ -393,18 +394,18 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- StringValue *meth1 = &engine->id_toString;
- StringValue *meth2 = &engine->id_valueOf;
+ String *meth1 = engine->id_toString();
+ String *meth2 = engine->id_valueOf();
if (typeHint == NUMBER_HINT)
qSwap(meth1, meth2);
Scope scope(engine);
ScopedCallData callData(scope, 0);
- callData->thisObject = object;
+ callData->thisObject = *object;
- ScopedValue conv(scope, object->get(*meth1));
- if (FunctionObject *o = conv->asFunctionObject()) {
+ ScopedValue conv(scope, object->get(meth1));
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -413,8 +414,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (engine->hasException)
return Encode::undefined();
- conv = object->get(*meth2);
- if (FunctionObject *o = conv->asFunctionObject()) {
+ conv = object->get(meth2);
+ if (FunctionObject *o = conv->as<FunctionObject>()) {
ScopedValue r(scope, o->call(callData));
if (r->isPrimitive())
return r->asReturnedValue();
@@ -437,7 +438,7 @@ Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Val
return engine->newBooleanObject(value.booleanValue());
case Value::Managed_Type:
Q_ASSERT(value.isString());
- return engine->newStringObject(value);
+ return engine->newStringObject(value.stringValue());
case Value::Integer_Type:
default: // double
return engine->newNumberObject(value.asDouble());
@@ -450,14 +451,14 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -467,7 +468,7 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -481,14 +482,14 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return engine->id_undefined->d();
+ return engine->id_undefined()->d();
case Value::Null_Type:
- return engine->id_null->d();
+ return engine->id_null()->d();
case Value::Boolean_Type:
if (value.booleanValue())
- return engine->id_true->d();
+ return engine->id_true()->d();
else
- return engine->id_false->d();
+ return engine->id_false()->d();
case Value::Managed_Type:
if (value.isString())
return value.stringValue()->d();
@@ -498,7 +499,7 @@ static Heap::String *convert_to_string_add(ExecutionEngine *engine, const Value
return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(engine, value.int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value.int_32());
default: // double
return RuntimeHelpers::stringFromNumber(engine, value.doubleValue());
} // switch
@@ -563,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;
@@ -578,7 +579,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object,
ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) {
return Encode::undefined();
}
@@ -660,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)
@@ -688,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
@@ -906,13 +905,13 @@ 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]);
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval))
+ 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);
return o->call(callData);
@@ -923,18 +922,17 @@ 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();
if (base)
callData->thisObject = base;
- FunctionObject *o = func->asFunctionObject();
+ FunctionObject *o = func->as<FunctionObject>();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
if (base)
@@ -943,17 +941,41 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI
return engine->throwTypeError(msg);
}
- if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
+ if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) {
return static_cast<EvalFunction *>(o)->evalCall(callData, true);
}
return o->call(callData);
}
+ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
+ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData)
+{
+ Scope scope(engine);
+ ScopedFunctionObject o(scope, getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex));
+ if (!o) {
+ QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ return engine->throwTypeError(error);
+ }
+
+ return o->call(callData);
+}
+
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());
@@ -979,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())
@@ -1019,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();
@@ -1031,13 +1053,12 @@ 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();
- Object *f = func->asObject();
+ Object *f = func->as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1046,7 +1067,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int
ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData)
{
- Object *f = func.asObject();
+ const Object *f = func.as<Object>();
if (!f)
return engine->throwTypeError();
@@ -1057,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();
@@ -1070,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())
@@ -1092,24 +1113,24 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value)
ScopedString res(scope);
switch (value.type()) {
case Value::Undefined_Type:
- res = engine->id_undefined;
+ res = engine->id_undefined();
break;
case Value::Null_Type:
- res = engine->id_object;
+ res = engine->id_object();
break;
case Value::Boolean_Type:
- res = engine->id_boolean;
+ res = engine->id_boolean();
break;
case Value::Managed_Type:
if (value.isString())
- res = engine->id_string;
- else if (value.objectValue()->asFunctionObject())
- res = engine->id_function;
+ res = engine->id_string();
+ else if (value.objectValue()->as<FunctionObject>())
+ res = engine->id_function();
else
- res = engine->id_object; // ### implementation-defined
+ res = engine->id_object(); // ### implementation-defined
break;
default:
- res = engine->id_number;
+ res = engine->id_number();
break;
}
return res.asReturnedValue();
@@ -1118,18 +1139,39 @@ 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);
}
+#ifndef V4_BOOTSTRAP
+ReturnedValue Runtime::typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context,
+ int propertyIndex)
+{
+ Scope scope(engine);
+ ScopedValue prop(scope, getQmlScopeObjectProperty(engine, context, propertyIndex));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return Runtime::typeofValue(engine, prop);
+}
+
+ReturnedValue Runtime::typeofContextObjectProperty(ExecutionEngine *engine, const Value &context,
+ int propertyIndex)
+{
+ Scope scope(engine);
+ ScopedValue prop(scope, getQmlContextObjectProperty(engine, context, propertyIndex));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return Runtime::typeofValue(engine, prop);
+}
+#endif // V4_BOOTSTRAP
+
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();
@@ -1148,14 +1190,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)
@@ -1163,46 +1197,48 @@ 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];
- ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype.asObject()));
+ QV4::InternalClass *klass = engine->current->compilationUnit->runtimeClasses[classId];
+ ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype()));
{
bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
@@ -1211,7 +1247,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);
@@ -1242,10 +1278,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
@@ -1329,32 +1365,14 @@ unsigned Runtime::doubleToUInt(const double &d)
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
-{
- return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
-}
-
-ReturnedValue Runtime::getQmlIdArray(NoThrowEngine *engine)
-{
- Q_ASSERT(engine->qmlContextObject());
- Scope scope(engine);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->idObjectsArray();
-}
-
-ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
+ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
- if (!context)
- return Encode::undefined();
- return QObjectWrapper::wrap(engine, context->contextObject);
+ return engine->qmlContext()->asReturnedValue();
}
-ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine)
+ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- return QObjectWrapper::wrap(engine, c->getScopeObject());
+ return engine->current->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1365,21 +1383,29 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Valu
engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->object(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired);
}
QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)
{
- Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
- QObject *scopeObject = c->getScopeObject();
+ QObject *scopeObject = engine->qmlScopeObject();
QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
QJSEngine *jsEngine = engine->jsEngine();
QQmlData::ensurePropertyCache(jsEngine, attachedObject);
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
+ return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true);
+}
+
+ReturnedValue Runtime::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false);
+}
+
+ReturnedValue Runtime::getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false);
}
ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)
@@ -1390,8 +1416,34 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c
scope.engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- ScopedContext ctx(scope, engine->currentContext());
- return QV4::QObjectWrapper::getProperty(wrapper->singletonObject(), ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired);
+}
+
+ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index)
+{
+ Scope scope(engine);
+ const QmlContext &qmlContext = static_cast<const QmlContext &>(c);
+ QQmlContextData *context = qmlContext.d()->qml->context;
+ if (!context || index >= (uint)context->idValueCount)
+ return Encode::undefined();
+
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ if (ep && ep->propertyCapture)
+ ep->propertyCapture->captureProperty(&context->idValues[index].bindings);
+
+ return QObjectWrapper::wrap(engine, context->idValues[index].data());
+}
+
+void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value);
+}
+
+void Runtime::setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)
+{
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value);
}
void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)
@@ -1402,13 +1454,12 @@ void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object
engine->throwTypeError(QStringLiteral("Cannot write property of null"));
return;
}
- ScopedContext ctx(scope, engine->currentContext());
- wrapper->setProperty(ctx, propertyIndex, value);
+ wrapper->setProperty(engine, propertyIndex, value);
}
ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(engine);
+ QQmlContextData *context = engine->callingQmlContext();
if (!context)
return Encode::undefined();
return context->importedScripts.value();
@@ -1417,18 +1468,17 @@ 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]);
- Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
- return wrapper->qmlSingletonWrapper(engine, name);
+ 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()) {
- *t = engine->globalObject()->asReturnedValue();
+ *t = engine->globalObject->asReturnedValue();
} else {
*t = t->toObject(engine)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index f2f90bbc15..0d81edca1e 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -33,9 +33,21 @@
#ifndef QMLJS_RUNTIME_H
#define QMLJS_RUNTIME_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4context_p.h"
+#include "qv4engine_p.h"
#include "qv4math_p.h"
#include <QtCore/qnumeric.h>
@@ -90,6 +102,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// call
static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
+ static ReturnedValue callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData);
static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData);
static ReturnedValue callElement(ExecutionEngine *engine, const Value &index, CallData *callData);
@@ -113,6 +127,8 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// typeof
static ReturnedValue typeofValue(ExecutionEngine *engine, const Value &val);
static ReturnedValue typeofName(ExecutionEngine *engine, int nameIndex);
+ static ReturnedValue typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex);
static ReturnedValue typeofElement(ExecutionEngine *engine, const Value &base, const Value &index);
@@ -206,19 +222,23 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static unsigned doubleToUInt(const double &d);
// qml
- static ReturnedValue getQmlIdArray(NoThrowEngine *ctx);
- static ReturnedValue getQmlImportedScripts(NoThrowEngine *ctx);
- static ReturnedValue getQmlContextObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlScopeObject(NoThrowEngine *ctx);
- static ReturnedValue getQmlSingleton(NoThrowEngine *ctx, int nameIndex);
+ static ReturnedValue getQmlContext(NoThrowEngine *engine);
+ static ReturnedValue getQmlImportedScripts(NoThrowEngine *engine);
+ static ReturnedValue getQmlSingleton(NoThrowEngine *engine, int nameIndex);
static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex);
+ static ReturnedValue getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
+ static ReturnedValue getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex);
static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired);
+ static ReturnedValue getQmlIdObject(ExecutionEngine *engine, const Value &context, uint index);
+
+ static void setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
+ static void setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value);
static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value);
};
struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
- static ReturnedValue objectDefaultValue(Object *object, int typeHint);
+ static ReturnedValue objectDefaultValue(const Object *object, int typeHint);
static ReturnedValue toPrimitive(const Value &value, int typeHint);
static double stringToNumber(const QString &s);
@@ -243,7 +263,7 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
#ifndef V4_BOOTSTRAP
inline ReturnedValue RuntimeHelpers::toPrimitive(const Value &value, int typeHint)
{
- Object *o = value.asObject();
+ const Object *o = value.as<Object>();
if (!o)
return value.asReturnedValue();
return RuntimeHelpers::objectDefaultValue(o, typeHint);
@@ -262,7 +282,7 @@ inline ReturnedValue Runtime::uPlus(const Value &value)
if (value.isNumber())
return value.asReturnedValue();
if (value.integerCompatible())
- return Encode(value.int_32);
+ return Encode(value.int_32());
double n = value.toNumberImpl();
return Encode(n);
@@ -369,6 +389,15 @@ inline ReturnedValue Runtime::div(const Value &left, const Value &right)
{
TRACE2(left, right);
+ if (Value::integerCompatible(left, right)) {
+ int lval = left.integerValue();
+ int rval = right.integerValue();
+ if (rval != 0 && (lval % rval == 0))
+ return Encode(int(lval / rval));
+ else
+ return Encode(double(lval) / rval);
+ }
+
double lval = left.toNumber();
double rval = right.toNumber();
return Primitive::fromDouble(lval / rval).asReturnedValue();
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 908248f0f0..d7fd44e1d6 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -33,6 +33,17 @@
#ifndef QV4SCOPEDVALUE_P_H
#define QV4SCOPEDVALUE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4engine_p.h"
#include "qv4value_p.h"
#include "qv4persistent_p.h"
@@ -54,18 +65,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 +78,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,13 +88,7 @@ struct Scope {
}
Value *alloc(int nValues) {
-#ifndef QT_NO_DEBUG
- size += nValues;
-#endif
- Value *ptr = engine->jsStackTop;
- engine->jsStackTop = ptr + nValues;
- memset(ptr, 0, nValues*sizeof(Value));
- return ptr;
+ return engine->jsAlloca(nValues);
}
bool hasException() const {
@@ -97,9 +97,6 @@ struct Scope {
ExecutionEngine *engine;
Value *mark;
-#ifndef QT_NO_DEBUG
- mutable int size;
-#endif
private:
Q_DISABLE_COPY(Scope)
@@ -110,49 +107,34 @@ struct ScopedValue
ScopedValue(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = 0;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(0);
}
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)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = o;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
-#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
+ ptr->setM(o);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = m->asReturnedValue();
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(m->asReturnedValue());
}
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = v;
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(v);
}
ScopedValue &operator=(const Value &v) {
@@ -161,9 +143,9 @@ struct ScopedValue
}
ScopedValue &operator=(Heap::Base *o) {
- ptr->m = o;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ ptr->setM(o);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
return *this;
}
@@ -174,7 +156,7 @@ struct ScopedValue
}
ScopedValue &operator=(const ReturnedValue &v) {
- ptr->val = v;
+ ptr->setRawValue(v);
return *this;
}
@@ -200,111 +182,78 @@ struct ScopedValue
template<typename T>
struct Scoped
{
- enum _Convert { Convert };
+ enum ConvertType { Convert };
- inline void setPointer(Managed *p) {
- ptr->m = p ? p->m : 0;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
+ inline void setPointer(const Managed *p) {
+ ptr->setM(p ? p->m() : 0);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
Scoped(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = 0;
-#if QT_POINTER_SIZE == 4
- ptr->tag = QV4::Value::Managed_Type;
-#endif
-#ifndef QT_NO_DEBUG
- ++scope.size;
+ ptr->setM(0);
+#ifndef QV4_USE_64_BIT_VALUE_ENCODING
+ ptr->setTag(QV4::Value::Managed_Type);
#endif
}
- // ### GC FIX casting below to be safe
Scoped(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v.as<T>());
}
Scoped(const Scope &scope, Heap::Base *o)
{
Value v;
v = o;
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v.as<T>());
}
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(value_cast<T>(*v.ptr));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v.ptr->as<T>());
}
- Scoped(const Scope &scope, const Value &v, _Convert)
+ Scoped(const Scope &scope, const Value &v, ConvertType)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, v);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(value_convert<T>(scope.engine, v));
}
Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsStackTop++;
- setPointer(v ? value_cast<T>(*v) : 0);
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(v ? v->as<T>() : 0);
}
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(value_cast<T>(QV4::Value::fromReturnedValue(v)));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
}
- Scoped(const Scope &scope, const ReturnedValue &v, _Convert)
+ Scoped(const Scope &scope, const ReturnedValue &v, ConvertType)
{
ptr = scope.engine->jsStackTop++;
- ptr->val = value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
+ ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
}
Scoped<T> &operator=(Heap::Base *o) {
- Value v;
- v = o;
- setPointer(value_cast<T>(v));
+ setPointer(Value::fromHeapObject(o).as<T>());
return *this;
}
Scoped<T> &operator=(typename T::Data *t) {
@@ -312,16 +261,16 @@ struct Scoped
return *this;
}
Scoped<T> &operator=(const Value &v) {
- setPointer(value_cast<T>(v));
+ setPointer(v.as<T>());
return *this;
}
Scoped<T> &operator=(Value *v) {
- setPointer(v ? value_cast<T>(*v) : 0);
+ setPointer(v ? v->as<T>() : 0);
return *this;
}
Scoped<T> &operator=(const ReturnedValue &v) {
- setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+ setPointer(QV4::Value::fromReturnedValue(v).as<T>());
return *this;
}
@@ -347,21 +296,21 @@ struct Scoped
}
bool operator!() const {
- return !ptr->m;
+ return !ptr->m();
}
operator void *() const {
- return ptr->m;
+ return ptr->m();
}
T *getPointer() {
return ptr->cast<T>();
}
- typename T::Data **getRef() {
- return reinterpret_cast<typename T::Data **>(&ptr->m);
+ Value *getRef() {
+ return ptr;
}
ReturnedValue asReturnedValue() const {
- return ptr->m ? ptr->val : Encode::undefined();
+ return ptr->m() ? ptr->rawValue() : Encode::undefined();
}
Value *ptr;
@@ -390,41 +339,14 @@ struct ScopedCallData {
inline Value &Value::operator =(const ScopedValue &v)
{
- val = v.ptr->val;
+ _val = v.ptr->val();
return *this;
}
template<typename T>
inline Value &Value::operator=(const Scoped<T> &t)
{
- val = t.ptr->val;
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(T *t)
-{
- m = t ? t->m : 0;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
-{
- m = v.ptr->m;
-#if QT_POINTER_SIZE == 4
- tag = Managed_Type;
-#endif
- return *this;
-}
-
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
-{
- val = t.val;
+ _val = t.ptr->val();
return *this;
}
@@ -447,29 +369,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->m = context->d();
-#if QT_POINTER_SIZE == 4
- savedContext->tag = QV4::Value::Managed_Type;
-#endif
- }
- ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
- : engine(context->engine)
- , savedContext(scope.alloc(1))
- {
- savedContext->m = context;
-#if QT_POINTER_SIZE == 4
- savedContext->tag = 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 4fde0e2445..7f2f22780e 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -32,11 +32,12 @@
****************************************************************************/
#include "qv4script_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4functionobject_p.h"
#include "qv4function_p.h"
#include "qv4context_p.h"
#include "qv4debugging_p.h"
+#include "qv4profiling_p.h"
#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
@@ -44,6 +45,7 @@
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4profiling_p.h>
#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include <private/qqmlcontextwrapper_p.h>
@@ -57,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
@@ -71,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
@@ -86,117 +97,52 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
- , qml(qml->d())
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false)
{
Q_ASSERT(scope->inUse());
function = f;
if (function)
function->compilationUnit->addref();
-
- Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
-
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
-
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
}
-Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml)
- : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
- , qml(qml->d())
+ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *callData)
{
- Q_ASSERT(scope->inUse());
-
- Scope s(scope);
- Scoped<QV4::QmlBindingWrapper> o(s, this);
-
- o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
-
- ScopedContext ctx(s, s.engine->currentContext());
- o->d()->qmlContext = ctx->newQmlContext(o, qml);
- s.engine->popContext();
-}
+ const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that);
+ ExecutionEngine *v4 = static_cast<const Object *>(that)->engine();
+ if (v4->hasException)
+ return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
-ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
-{
- ExecutionEngine *engine = static_cast<Object *>(that)->engine();
- CHECK_STACK_LIMITS(engine);
+ Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope);
- Scope scope(engine);
- QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
- if (!This->function())
+ QV4::Function *f = This->function();
+ if (!f)
return QV4::Encode::undefined();
- Scoped<CallContext> ctx(scope, This->d()->qmlContext);
- std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue());
- engine->pushContext(ctx);
- ScopedValue result(scope, This->function()->code(engine, This->function()->codeData));
- engine->popContext();
+ Scoped<CallContext> ctx(scope, v4->currentContext->newCallContext(This, callData));
+ v4->pushContext(ctx);
- return result->asReturnedValue();
-}
-
-void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e)
-{
- QmlBindingWrapper::Data *wrapper = static_cast<QmlBindingWrapper::Data *>(m);
- if (wrapper->qml)
- wrapper->qml->mark(e);
- FunctionObject::markObjects(m, e);
- if (wrapper->qmlContext)
- wrapper->qmlContext->mark(e);
-}
-
-static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
-{
- QV4::Scope scope(ctx);
- QV4::Scoped<CallContext> signalEmittingContext(scope, static_cast<Heap::CallContext *>(ctx->d()->parent));
- Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext);
- return signalEmittingContext->argument(parameterIndex);
-}
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f));
-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::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
- ScopedContext global(valueScope, valueScope.engine->rootContext());
- QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScopeObject));
- QV4::Scoped<CallContext> wrapperContext(valueScope, wrapper->context());
-
- 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();
+ return result->asReturnedValue();
}
-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);
}
}
@@ -214,7 +160,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -267,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);
}
@@ -285,23 +231,22 @@ ReturnedValue Script::run()
if (!vmFunction)
return Encode::undefined();
- QV4::ExecutionEngine *engine = scope->engine;
+ 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->strictMode = vmFunction->isStrict();
- scope->lookups = vmFunction->compilationUnit->runtimeLookups;
- scope->compilationUnit = vmFunction->compilationUnit;
+ scope->d()->strictMode = vmFunction->isStrict();
+ scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->d()->compilationUnit = vmFunction->compilationUnit;
- return vmFunction->code(engine, vmFunction->codeData);
+ return Q_V4_PROFILE(engine, vmFunction);
} else {
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(ctx, 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);
@@ -376,18 +321,17 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
- ScopedObject qmlObj(valueScope, qml.value());
- ScopedContext ctx(valueScope, scope);
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(ctx, 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 05a9e45f45..4fecf62082 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -33,9 +33,21 @@
#ifndef QV4SCRIPT_H
#define QV4SCRIPT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
#include "qv4engine_p.h"
#include "qv4functionobject_p.h"
+#include "qv4context_p.h"
#include <QQmlError>
@@ -63,7 +75,7 @@ struct ContextStateSaver {
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
{
- savedContext->m = context->d();
+ savedContext->setM(context->d());
}
ContextStateSaver(Scope &scope, Heap::ExecutionContext *context)
: savedContext(scope.alloc(1))
@@ -72,12 +84,12 @@ struct ContextStateSaver {
, compilationUnit(context->compilationUnit)
, lineNumber(context->lineNumber)
{
- savedContext->m = context;
+ savedContext->setM(context);
}
~ContextStateSaver()
{
- Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m);
+ Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m());
ctx->strictMode = strictMode;
ctx->lookups = lookups;
ctx->compilationUnit = compilationUnit;
@@ -85,52 +97,29 @@ struct ContextStateSaver {
}
};
-namespace Heap {
-struct QmlBindingWrapper : Heap::FunctionObject {
- QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml);
- // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
- QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml);
- Object *qml;
- CallContext *qmlContext;
-};
-
-}
-
-struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
- V4_OBJECT2(QmlBindingWrapper, FunctionObject)
-
- static ReturnedValue call(Managed *that, CallData *);
- static void markObjects(Heap::Base *m, ExecutionEngine *e);
-
- Heap::CallContext *context() const { return d()->qmlContext; }
-
- static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
- const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
-
-private:
-};
-
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->d()), strictMode(false), inheritContext(false), parsed(false)
+ , 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;
int column;
QString sourceCode;
- // ### GC
- Heap::ExecutionContext *scope;
+ ExecutionContext *scope;
bool strictMode;
bool inheritContext;
bool parsed;
- QV4::PersistentValue qml;
+ QV4::PersistentValue qmlContext;
QV4::PersistentValue compilationUnitHolder;
Function *vmFunction;
bool parseAsBinding;
@@ -144,7 +133,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 f1f546bece..36ee848d00 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -175,7 +175,7 @@ template <> QUrl convertValueToElement(const Value &value)
template <> QModelIndex convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().toModelIndex();
return QModelIndex();
@@ -183,7 +183,7 @@ template <> QModelIndex convertValueToElement(const Value &value)
template <> QItemSelectionRange convertValueToElement(const Value &value)
{
- const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value);
+ const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
if (v)
return v->toVariant().value<QItemSelectionRange>();
return QItemSelectionRange();
@@ -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:
@@ -231,7 +232,7 @@ public:
defineAccessorProperty(QStringLiteral("length"), method_get_length, method_set_length);
}
- QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty)
+ QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) const
{
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
@@ -316,9 +317,9 @@ public:
return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- void containerAdvanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
*index = UINT_MAX;
if (d()->isReference) {
@@ -400,7 +401,7 @@ public:
ScopedCallData callData(scope, 2);
callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
- callData->thisObject = this->m_ctx->d()->engine->globalObject();
+ callData->thisObject = this->m_ctx->d()->engine->globalObject;
QV4::ScopedValue result(scope, compare->call(callData));
return result->toNumber() < 0;
}
@@ -419,7 +420,7 @@ public:
}
QV4::Scope scope(ctx);
- if (ctx->argc() == 1 && ctx->args()[0].asFunctionObject()) {
+ if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) {
CompareFunctor cf(ctx, ctx->args()[0]);
std::sort(d()->container.begin(), d()->container.end(), cf);
} else {
@@ -526,8 +527,8 @@ public:
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
- static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
- { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
+ static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty)
+ { return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
static void putIndexed(Managed *that, uint index, const QV4::Value &value)
{ static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
@@ -536,33 +537,31 @@ public:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void advanceIterator(Managed *that, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
};
template <typename Container>
-Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject())
- , 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.asObject())
- , 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();
@@ -605,7 +604,7 @@ void SequencePrototype::init()
{
FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
}
#undef REGISTER_QML_SEQUENCE_METATYPE
@@ -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
@@ -700,11 +699,11 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
{
*succeeded = true;
- if (!array.asArrayObject()) {
+ if (!array.as<ArrayObject>()) {
*succeeded = false;
return QVariant();
}
- QV4::Scope scope(array.asObject()->engine());
+ QV4::Scope scope(array.as<Object>()->engine());
QV4::ScopedArrayObject a(scope, array);
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
@@ -717,7 +716,7 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
return qMetaTypeId<SequenceType>(); \
} else
-int SequencePrototype::metaTypeForSequence(QV4::Object *object)
+int SequencePrototype::metaTypeForSequence(const QV4::Object *object)
{
FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE)
/*else*/ {
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 9949278a89..560c3c27ca 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -48,9 +48,10 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4object_p.h"
#include "qv4context_p.h"
+#include "qv4string_p.h"
QT_BEGIN_NAMESPACE
@@ -70,7 +71,7 @@ struct SequencePrototype : public QV4::Object
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
- static int metaTypeForSequence(Object *object);
+ static int metaTypeForSequence(const Object *object);
static QVariant toVariant(Object *object);
static QVariant toVariant(const Value &array, int typeHint, bool *succeeded);
};
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 31d85df13e..33b40796a4 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -37,7 +37,7 @@
#include <private/qqmllistmodel_p.h>
#include <private/qqmllistmodelworkeragent_p.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qv4sequenceobject_p.h>
@@ -168,11 +168,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, qstr.constData(), length*sizeof(QChar));
- } else if (v.asFunctionObject()) {
+ } else if (v.as<FunctionObject>()) {
// XXX TODO: Implement passing function objects between the main and
// worker scripts
push(data, valueheader(WorkerUndefined));
- } else if (QV4::ArrayObject *array = v.asArrayObject()) {
+ } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) {
uint length = array->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -195,11 +195,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerNumber));
push(data, v.asDouble());
- } else if (QV4::DateObject *d = v.asDateObject()) {
+ } else if (const QV4::DateObject *d = v.as<DateObject>()) {
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerDate));
- push(data, d->date().asDouble());
- } else if (RegExpObject *re = v.as<RegExpObject>()) {
+ push(data, d->date());
+ } else if (const RegExpObject *re = v.as<RegExpObject>()) {
quint32 flags = re->flags();
QString pattern = re->source();
int length = pattern.length() + 1;
@@ -218,7 +218,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
char *buffer = data.data() + offset;
memcpy(buffer, pattern.constData(), length*sizeof(QChar));
- } else if (QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
+ } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
// XXX TODO: Generalize passing objects between the main thread and worker scripts so
// that others can trivially plug in their elements.
QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
@@ -231,10 +231,10 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
}
// No other QObject's are allowed to be sent
push(data, valueheader(WorkerUndefined));
- } else if (Object *o = v.asObject()) {
+ } else if (const Object *o = v.as<Object>()) {
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint seqLength = ScopedValue(scope, o->get(engine->id_length))->toUInt32();
+ uint seqLength = ScopedValue(scope, o->get(engine->id_length()))->toUInt32();
uint length = seqLength + 1;
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -265,7 +265,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
s = properties->getIndexed(ii);
serialize(data, s, engine);
- QV4::String *str = s->asString();
+ QV4::String *str = s->as<String>();
val = o->get(str);
if (scope.hasException())
scope.engine->catchException();
@@ -356,7 +356,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
QVariant var = qVariantFromValue(ref);
QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
- rv->asObject()->defineReadonlyProperty(s, v);
+ rv->as<Object>()->defineReadonlyProperty(s, v);
agent->release();
agent->setEngine(engine);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index 06eaffe4c4..d5d48edee7 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -46,7 +46,7 @@
//
#include <QtCore/qbytearray.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
QT_BEGIN_NAMESPACE
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/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 861c7dd28d..136f26a25c 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -34,12 +34,19 @@
#ifndef QV4SPARSEARRAY_H
#define QV4SPARSEARRAY_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
-#include <QtCore/qmap.h>
-#include "qv4value_inl_p.h"
-#include "qv4scopedvalue_p.h"
-#include "qv4property_p.h"
-#include <assert.h>
+#include <QtCore/qlist.h>
//#define Q_MAP_DEBUG
#ifdef Q_MAP_DEBUG
@@ -188,7 +195,7 @@ public:
typedef qptrdiff difference_type;
typedef int size_type;
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
void dump() const;
#endif
};
@@ -261,7 +268,7 @@ inline void SparseArray::push_back(uint index, uint len)
n->value = index;
}
-#ifndef QT_NO_DEBUG
+#ifdef Q_MAP_DEBUG
inline void SparseArray::dump() const
{
const SparseArrayNode *it = begin();
@@ -344,4 +351,4 @@ inline SparseArrayNode *SparseArray::upperBound(uint akey)
QT_END_NAMESPACE
-#endif // QMAP_H
+#endif
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 6d55eb2c18..24a13ddd10 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include "qv4string_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#ifndef V4_BOOTSTRAP
#include "qv4identifiertable_p.h"
#include "qv4runtime_p.h"
@@ -110,7 +110,7 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- if (!o->d()->vtable->isString)
+ if (!o->d()->vtable()->isString)
return false;
return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 1cf8f51a29..85433369fc 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -33,6 +33,17 @@
#ifndef QV4STRING_H
#define QV4STRING_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qstring.h>
#include "qv4managed_p.h"
@@ -188,6 +199,20 @@ public:
static uint toArrayIndex(const QString &str);
};
+template<>
+inline const String *Value::as() const {
+ return isManaged() && m() && m()->vtable()->isString ? static_cast<const String *>(this) : 0;
+}
+
+#ifndef V4_BOOTSTRAP
+template<>
+inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
+{
+ return v.toString(e)->asReturnedValue();
+}
+#endif
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index e0b84f6da3..757ec6c6bf 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -36,7 +36,7 @@
#include "qv4regexp_p.h"
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4alloca_p.h"
#include <QtCore/QDateTime>
@@ -67,68 +67,62 @@ 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());
- value = ic->engine->newString()->asReturnedValue();
- tmpProperty.value = Primitive::undefinedValue();
-
- Scope scope(ic->engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0));
+ Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
+ string = internalClass->engine->id_empty()->d();
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
}
-Heap::StringObject::StringObject(ExecutionEngine *engine, const Value &val)
- : Heap::Object(engine->emptyClass, engine->stringPrototype.asObject())
+Heap::StringObject::StringObject(const QV4::String *str)
{
- value = val;
- Q_ASSERT(value.isString());
- tmpProperty.value = Primitive::undefinedValue();
-
- Scope scope(engine);
- ScopedObject s(scope, this);
- s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
+ string = str->d();
+ *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
}
-Property *Heap::StringObject::getIndex(uint index) const
+Heap::String *Heap::StringObject::getIndex(uint index) const
{
- QString str = value.stringValue()->toQString();
+ QString str = string->toQString();
if (index >= (uint)str.length())
return 0;
- tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1)));
- return &tmpProperty;
+ return internalClass->engine->newString(str.mid(index, 1));
+}
+
+uint Heap::StringObject::length() const
+{
+ return string->len;
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
{
ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine();
Scope scope(v4);
- Scoped<StringObject> o(scope, m->asStringObject());
+ Scoped<StringObject> o(scope, m->as<StringObject>());
Q_ASSERT(!!o);
- if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) {
- if (v4->currentContext()->strictMode)
+ if (index < static_cast<uint>(o->d()->string->toQString().length())) {
+ if (v4->current->strictMode)
v4->throwTypeError();
return false;
}
return true;
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- *name = (Heap::String *)0;
+ name->setM(0);
StringObject *s = static_cast<StringObject *>(m);
- uint slen = s->d()->value.stringValue()->toQString().length();
+ uint slen = s->d()->string->toQString().length();
if (it->arrayIndex <= slen) {
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
PropertyAttributes a;
- Property *pd = s->__getOwnProperty__(*index, &a);
+ Property pd;
+ s->getOwnProperty(*index, &a, &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
- p->copy(pd, a);
+ p->copy(&pd, a);
return;
}
}
@@ -146,8 +140,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String
void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
StringObject::Data *o = static_cast<StringObject::Data *>(that);
- o->value.stringValue()->mark(e);
- o->tmpProperty.value.mark(e);
+ o->string->mark(e);
Object::markObjects(that, e);
}
@@ -158,11 +151,11 @@ Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope)
{
}
-ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
+ReturnedValue StringCtor::construct(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
- ScopedValue value(scope);
+ ScopedString value(scope);
if (callData->argc)
value = callData->args[0].toString(v4);
else
@@ -170,9 +163,9 @@ ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
return Encode(v4->newStringObject(value));
}
-ReturnedValue StringCtor::call(Managed *m, CallData *callData)
+ReturnedValue StringCtor::call(const Managed *m, CallData *callData)
{
- ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
+ ExecutionEngine *v4 = static_cast<const Object *>(m)->engine();
Scope scope(v4);
ScopedValue value(scope);
if (callData->argc)
@@ -187,13 +180,13 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
ctor->defineDefaultProperty(QStringLiteral("fromCharCode"), method_fromCharCode, 1);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
- defineDefaultProperty(engine->id_toString, method_toString);
- defineDefaultProperty(engine->id_valueOf, method_toString); // valueOf and toString are identical
+ defineDefaultProperty(engine->id_toString(), method_toString);
+ defineDefaultProperty(engine->id_valueOf(), method_toString); // valueOf and toString are identical
defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1);
defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1);
defineDefaultProperty(QStringLiteral("concat"), method_concat, 1);
@@ -220,8 +213,8 @@ static QString getThisString(ExecutionContext *ctx)
ScopedValue t(scope, ctx->thisObject());
if (t->isString())
return t->stringValue()->toQString();
- if (StringObject *thisString = t->asStringObject())
- return thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = t->as<StringObject>())
+ return thisString->d()->string->toQString();
if (t->isUndefined() || t->isNull()) {
scope.engine->throwTypeError();
return QString();
@@ -234,10 +227,10 @@ ReturnedValue StringPrototype::method_toString(CallContext *context)
if (context->thisObject().isString())
return context->thisObject().asReturnedValue();
- StringObject *o = context->thisObject().asStringObject();
+ StringObject *o = context->thisObject().as<StringObject>();
if (!o)
return context->engine()->throwTypeError();
- return o->d()->value.asReturnedValue();
+ return Encode(o->d()->string);
}
ReturnedValue StringPrototype::method_charAt(CallContext *context)
@@ -368,7 +361,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (!rx) {
ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ rx = context->d()->engine->regExpCtor()->construct(callData);
}
if (!rx)
@@ -379,7 +372,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
// ### use the standard builtin function, not the one that might be redefined in the proto
ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec")));
- ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString));
+ ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString));
ScopedCallData callData(scope, 1);
callData->thisObject = rx;
@@ -470,8 +463,8 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
{
Scope scope(ctx);
QString string;
- if (StringObject *thisString = ctx->thisObject().asStringObject())
- string = thisString->d()->value.stringValue()->toQString();
+ if (StringObject *thisString = ctx->thisObject().as<StringObject>())
+ string = thisString->d()->string->toQString();
else
string = ctx->thisObject().toQString();
@@ -481,12 +474,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint allocatedMatchOffsets = 64;
uint _matchOffsets[64];
uint *matchOffsets = _matchOffsets;
- uint nMatchOffsets = 0;
ScopedValue searchValue(scope, ctx->argument(0));
Scoped<RegExpObject> regExp(scope, searchValue);
if (regExp) {
uint offset = 0;
+ uint nMatchOffsets = 0;
// We extract the pointer here to work around a compiler bug on Android.
Scoped<RegExp> re(scope, regExp->value());
@@ -510,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 {
@@ -519,7 +512,6 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
int idx = string.indexOf(searchString);
if (idx != -1) {
numStringMatches = 1;
- nMatchOffsets = 2;
matchOffsets[0] = idx;
matchOffsets[1] = idx + searchString.length();
}
@@ -593,7 +585,7 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
- regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
+ regExpValue = ctx->d()->engine->regExpCtor()->construct(callData);
if (scope.engine->hasException)
return Encode::undefined();
regExp = regExpValue->as<RegExpObject>();
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 459dc1322e..7d4f78d3c5 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -33,6 +33,17 @@
#ifndef QV4STRINGOBJECT_P_H
#define QV4STRINGOBJECT_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include <QtCore/qnumeric.h>
@@ -44,13 +55,16 @@ namespace QV4 {
namespace Heap {
struct StringObject : Object {
- StringObject(InternalClass *ic, QV4::Object *prototype);
- StringObject(ExecutionEngine *engine, const Value &value);
- Value value;
+ enum {
+ LengthPropertyIndex = 0
+ };
+
+ StringObject();
+ StringObject(const QV4::String *string);
+ String *string;
- Property *getIndex(uint index) const;
- // ### get rid of tmpProperty
- mutable Property tmpProperty;
+ Heap::String *getIndex(uint index) const;
+ uint length() const;
};
struct StringCtor : FunctionObject {
@@ -62,15 +76,20 @@ struct StringCtor : FunctionObject {
struct StringObject: Object {
V4_OBJECT2(StringObject, Object)
Q_MANAGED_TYPE(StringObject)
+ V4_INTERNALCLASS(stringClass)
+ V4_PROTOTYPE(stringPrototype)
- Property *getIndex(uint index) const {
+ Heap::String *getIndex(uint index) const {
return d()->getIndex(index);
}
+ uint length() const {
+ return d()->length();
+ }
static bool deleteIndexedProperty(Managed *m, uint index);
protected:
- static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
@@ -78,8 +97,8 @@ struct StringCtor: FunctionObject
{
V4_OBJECT2(StringCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
struct StringPrototype: StringObject
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 19e541dba8..b45bbb713c 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qv4typedarray_p.h"
#include "qv4arraybuffer_p.h"
+#include "qv4string_p.h"
#include <cmath>
@@ -201,10 +202,10 @@ Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::T
{
}
-ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArrayCtor> that(scope, static_cast<TypedArrayCtor *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArrayCtor> that(scope, static_cast<const TypedArrayCtor *>(m));
if (!callData->argc || !callData->args[0].isObject()) {
// ECMA 6 22.2.1.1
@@ -215,11 +216,11 @@ ReturnedValue TypedArrayCtor::construct(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;
@@ -235,11 +236,11 @@ ReturnedValue TypedArrayCtor::construct(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;
@@ -257,7 +258,7 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
TypedArrayWrite write =array->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*destElementSize, val);
}
}
@@ -289,7 +290,7 @@ ReturnedValue TypedArrayCtor::construct(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;
@@ -299,16 +300,16 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
// ECMA 6 22.2.1.3
ScopedObject o(scope, callData->argument(0));
- uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length))->toInteger(), (double)UINT_MAX);
+ uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length()))->toInteger(), (double)UINT_MAX);
if (scope.engine->hasException)
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;
@@ -329,28 +330,32 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
return array.asReturnedValue();
}
-ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData)
+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].asObject()),
- 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);
Object::markObjects(that, e);
}
-ReturnedValue TypedArray::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty)
{
- Scope scope(static_cast<Object *>(m)->engine());
- Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+ Scope scope(static_cast<const Object *>(m)->engine());
+ Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
@@ -382,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();
}
@@ -390,10 +395,10 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
- ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
- defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineDefaultProperty(engine->id_constructor(), (o = ctor));
defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
@@ -470,7 +475,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
if (scope.engine->hasException || !o)
return scope.engine->throwTypeError();
- double len = ScopedValue(scope, o->get(scope.engine->id_length))->toNumber();
+ double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber();
uint l = (uint)len;
if (scope.engine->hasException || l != len)
return scope.engine->throwTypeError();
@@ -523,7 +528,7 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
TypedArrayWrite write = a->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.val = read(src, i*srcElementSize);
+ val.setRawValue(read(src, i*srcElementSize));
write(scope.engine, dest, i*elementSize, val);
}
@@ -563,7 +568,7 @@ ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
int newLen = end - begin;
- ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor()));
if (!constructor)
return scope.engine->throwTypeError();
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index afd1bb97e7..67e04c8ac0 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -33,6 +33,17 @@
#ifndef QV4TYPEDARRAY_H
#define QV4TYPEDARRAY_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4arraybuffer_p.h"
@@ -69,10 +80,10 @@ struct TypedArray : Object {
NTypes
};
- TypedArray(ExecutionEngine *e, Type t);
+ TypedArray(Type t);
const TypedArrayOperations *type;
- ArrayBuffer *buffer;
+ Pointer<ArrayBuffer> buffer;
uint byteLength;
uint byteOffset;
Type arrayType;
@@ -85,7 +96,7 @@ struct TypedArrayCtor : FunctionObject {
};
struct TypedArrayPrototype : Object {
- inline TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t);
+ inline TypedArrayPrototype(TypedArray::Type t);
TypedArray::Type type;
};
@@ -96,6 +107,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;
}
@@ -113,7 +126,7 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
}
static void markObjects(Heap::Base *that, ExecutionEngine *e);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const Value &value);
};
@@ -121,8 +134,8 @@ struct TypedArrayCtor: FunctionObject
{
V4_OBJECT2(TypedArrayCtor, FunctionObject)
- static ReturnedValue construct(Managed *m, CallData *callData);
- static ReturnedValue call(Managed *that, CallData *callData);
+ static ReturnedValue construct(const Managed *m, CallData *callData);
+ static ReturnedValue call(const Managed *that, CallData *callData);
};
@@ -142,9 +155,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/qv4util_p.h b/src/qml/jsruntime/qv4util_p.h
index f9ae37855e..329831f134 100644
--- a/src/qml/jsruntime/qv4util_p.h
+++ b/src/qml/jsruntime/qv4util_p.h
@@ -33,6 +33,17 @@
#ifndef QV4UTIL_H
#define QV4UTIL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "qv4global_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 68228f06bb..4c81199a07 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -32,10 +32,11 @@
****************************************************************************/
#include <qv4engine_p.h>
#include <qv4runtime_p.h>
+#include <qv4string_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
-#include "qv4mm_p.h"
+#include <private/qv4mm_p.h>
#endif
#include <wtf/MathExtras.h>
@@ -68,10 +69,32 @@ int Value::toUInt16() const
return (unsigned short)number;
}
+bool Value::toBoolean() const
+{
+ switch (type()) {
+ case Value::Undefined_Type:
+ case Value::Null_Type:
+ return false;
+ case Value::Boolean_Type:
+ case Value::Integer_Type:
+ return (bool)int_32();
+ case Value::Managed_Type:
+#ifdef V4_BOOTSTRAP
+ Q_UNIMPLEMENTED();
+#else
+ if (isString())
+ return stringValue()->toQString().length() > 0;
+#endif
+ return true;
+ default: // double
+ return doubleValue() && !std::isnan(doubleValue());
+ }
+}
+
double Value::toInteger() const
{
if (integerCompatible())
- return int_32;
+ return int_32();
return Primitive::toInteger(toNumber());
}
@@ -87,10 +110,10 @@ double Value::toNumberImpl() const
#else
if (isString())
return RuntimeHelpers::stringToNumber(stringValue()->toQString());
- {
- Q_ASSERT(isObject());
- Scope scope(objectValue()->engine());
- ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
+ {
+ Q_ASSERT(isObject());
+ Scope scope(objectValue()->engine());
+ ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT));
if (scope.engine->hasException)
return 0;
return prim->toNumber();
@@ -99,7 +122,7 @@ double Value::toNumberImpl() const
case QV4::Value::Null_Type:
case QV4::Value::Boolean_Type:
case QV4::Value::Integer_Type:
- return int_32;
+ return int_32();
default: // double
Q_UNREACHABLE();
}
@@ -148,7 +171,7 @@ QString Value::toQStringNoThrow() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -184,7 +207,7 @@ QString Value::toQString() const
}
case Value::Integer_Type: {
QString str;
- RuntimeHelpers::numberToString(&str, (double)int_32, 10);
+ RuntimeHelpers::numberToString(&str, (double)int_32(), 10);
return str;
}
default: { // double
@@ -197,14 +220,14 @@ QString Value::toQString() const
#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
- if (val == other.val)
+ if (_val == other._val)
return true;
if (isString() && other.isString())
return stringValue()->isEqualTo(other.stringValue());
if (isInteger() && other.isDouble())
- return int_32 ? (double(int_32) == other.doubleValue()) : (other.val == 0);
+ return int_32() ? (double(int_32()) == other.doubleValue()) : (other._val == 0);
if (isDouble() && other.isInteger())
- return other.int_32 ? (doubleValue() == double(other.int_32)) : (val == 0);
+ return other.int_32() ? (doubleValue() == double(other.int_32())) : (_val == 0);
return false;
}
@@ -281,4 +304,35 @@ Heap::Object *Value::toObject(ExecutionEngine *e) const
return RuntimeHelpers::convertToObject(e, *this);
}
+uint Value::asArrayLength(bool *ok) const
+{
+ *ok = true;
+ if (isInteger()) {
+ if (int_32() >= 0) {
+ return (uint)int_32();
+ } else {
+ *ok = false;
+ return UINT_MAX;
+ }
+ }
+ if (isNumber()) {
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+ }
+ if (isString())
+ return stringValue()->toUInt(ok);
+
+ uint idx = toUInt32();
+ double d = toNumber();
+ if (d != idx) {
+ *ok = false;
+ return UINT_MAX;
+ }
+ return idx;
+}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
deleted file mode 100644
index f3026900d6..0000000000
--- a/src/qml/jsruntime/qv4value_inl_p.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QV4VALUE_INL_H
-#define QV4VALUE_INL_H
-
-#include <cmath> // this HAS to come
-
-#include "qv4value_p.h"
-
-#include "qv4string_p.h"
-#include "qv4managed_p.h"
-#include "qv4engine_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-
-inline bool Value::isString() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isString;
-}
-inline bool Value::isObject() const
-{
- if (!isManaged())
- return false;
- return m && m->vtable->isObject;
-}
-
-inline bool Value::isPrimitive() const
-{
- return !isObject();
-}
-
-inline String *Value::asString() const
-{
- if (isString())
- return stringValue();
- return 0;
-}
-
-inline void Value::mark(ExecutionEngine *e) const
-{
- if (!val)
- return;
- Managed *m = asManaged();
- if (m)
- m->mark(e);
-}
-
-inline Primitive Primitive::nullValue()
-{
- Primitive v;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(_Null_Type) << Tag_Shift;
-#else
- v.tag = _Null_Type;
- v.int_32 = 0;
-#endif
- return v;
-}
-
-inline Primitive Primitive::fromBoolean(bool b)
-{
- Primitive v;
- v.tag = _Boolean_Type;
- v.int_32 = (bool)b;
- return v;
-}
-
-inline Primitive Primitive::fromDouble(double d)
-{
- Primitive v;
- v.setDouble(d);
- return v;
-}
-
-inline Primitive Primitive::fromInt32(int i)
-{
- Primitive v;
- v.tag = _Integer_Type;
- v.int_32 = i;
- return v;
-}
-
-inline Primitive Primitive::fromUInt32(uint i)
-{
- Primitive v;
- if (i < INT_MAX) {
- v.tag = _Integer_Type;
- v.int_32 = (int)i;
- } else {
- v.setDouble(i);
- }
- return v;
-}
-
-inline double Value::toNumber() const
-{
- if (isInteger())
- return int_32;
- if (isDouble())
- return doubleValue();
- return toNumberImpl();
-}
-
-inline int Value::toInt32() const
-{
- if (isInteger())
- return int_32;
- double d = isNumber() ? doubleValue() : toNumberImpl();
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Primitive::toInt32(d);
-}
-
-inline unsigned int Value::toUInt32() const
-{
- return (unsigned int)toInt32();
-}
-
-
-inline bool Value::toBoolean() const
-{
- switch (type()) {
- case Value::Undefined_Type:
- case Value::Null_Type:
- return false;
- case Value::Boolean_Type:
- case Value::Integer_Type:
- return (bool)int_32;
- case Value::Managed_Type:
-#ifdef V4_BOOTSTRAP
- Q_UNIMPLEMENTED();
-#else
- if (isString())
- return stringValue()->toQString().length() > 0;
-#endif
- return true;
- default: // double
- return doubleValue() && !std::isnan(doubleValue());
- }
-}
-
-#ifndef V4_BOOTSTRAP
-inline uint Value::asArrayIndex() const
-{
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- if (!isNumber())
- return UINT_MAX;
- if (isInteger())
- return int_32 >= 0 ? (uint)int_32 : UINT_MAX;
-#else
- if (isInteger() && int_32 >= 0)
- return (uint)int_32;
- if (!isDouble())
- return UINT_MAX;
-#endif
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d)
- return UINT_MAX;
- return idx;
-}
-
-inline uint Value::asArrayLength(bool *ok) const
-{
- *ok = true;
- if (isInteger()) {
- if (int_32 >= 0) {
- return (uint)int_32;
- } else {
- *ok = false;
- return UINT_MAX;
- }
- }
- if (isNumber()) {
- double d = doubleValue();
- uint idx = (uint)d;
- if (idx != d) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
- }
- if (isString())
- return stringValue()->toUInt(ok);
-
- uint idx = toUInt32();
- double d = toNumber();
- if (d != idx) {
- *ok = false;
- return UINT_MAX;
- }
- return idx;
-}
-
-inline Object *Value::asObject() const
-{
- return isObject() ? objectValue() : 0;
-}
-
-inline FunctionObject *Value::asFunctionObject() const
-{
- return isObject() ? managed()->asFunctionObject() : 0;
-}
-
-inline NumberObject *Value::asNumberObject() const
-{
- return isObject() ? managed()->asNumberObject() : 0;
-}
-
-inline StringObject *Value::asStringObject() const
-{
- return isObject() ? managed()->asStringObject() : 0;
-}
-
-inline DateObject *Value::asDateObject() const
-{
- return isObject() ? managed()->asDateObject() : 0;
-}
-
-inline ArrayObject *Value::asArrayObject() const
-{
- return isObject() ? managed()->asArrayObject() : 0;
-}
-
-inline ErrorObject *Value::asErrorObject() const
-{
- return isObject() ? managed()->asErrorObject() : 0;
-}
-
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
-
-#ifndef V4_BOOTSTRAP
-
-template<>
-inline String *value_cast(const Value &v) {
- return v.asString();
-}
-
-template<>
-inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
-{
- return v.toString(e)->asReturnedValue();
-}
-
-#endif
-
-#endif
-
-} // namespace QV4
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 628950784a..089b2bbd34 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -33,10 +33,22 @@
#ifndef QV4VALUE_P_H
#define QV4VALUE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <limits.h>
#include <QtCore/QString>
#include "qv4global_p.h"
+#include <private/qv4heap_p.h>
/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects
are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */
@@ -50,56 +62,12 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-typedef uint Bool;
-
namespace Heap {
-
-struct Q_QML_EXPORT Base {
- union {
- const ManagedVTable *vtable;
- quintptr mm_data;
- };
-
- inline ReturnedValue asReturnedValue() const;
- inline void mark(QV4::ExecutionEngine *engine);
-
- enum {
- MarkBit = 0x1,
- NotInUse = 0x2,
- PointerMask = ~0x3
- };
-
- ManagedVTable *gcGetVtable() const {
- return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask);
- }
- inline bool isMarked() const {
- return mm_data & MarkBit;
- }
- inline void setMarkBit() {
- mm_data |= MarkBit;
- }
- inline void clearMarkBit() {
- mm_data &= ~MarkBit;
- }
-
- inline bool inUse() const {
- return !(mm_data & NotInUse);
- }
-
- Base *nextFree() {
- return reinterpret_cast<Base *>(mm_data & PointerMask);
- }
- void setNextFree(Base *m) {
- mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
- }
-
- void *operator new(size_t, Managed *m) { return m; }
- void *operator new(size_t, Heap::Base *m) { return m; }
- void operator delete(void *, Heap::Base *) {}
-};
-
+ struct Base;
}
+typedef uint Bool;
+
struct Q_QML_PRIVATE_EXPORT Value
{
/*
@@ -124,30 +92,38 @@ struct Q_QML_PRIVATE_EXPORT Value
Bit 15-17 is then used to encode other immediates.
*/
+ quint64 _val;
+
+ Q_ALWAYS_INLINE quint64 val() const { return _val; }
+ Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; }
+ Q_ALWAYS_INLINE void setValue(quint32 v) { memcpy(&_val, &v, 4); }
+ Q_ALWAYS_INLINE void setTag(quint32 t) { memcpy(4 + (quint8 *)&_val, &t, 4); }
- union {
- quint64 val;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#else
- double dbl;
-#endif
- struct {
-#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
- uint tag;
-#endif
- union {
- uint uint_32;
- int int_32;
-#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- Heap::Base *m;
-#endif
- };
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- uint tag;
+ static inline int valueOffset() { return 0; }
+ static inline int tagOffset() { return 4; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
+ Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
+#else // !Q_LITTLE_ENDIAN
+ static inline int valueOffset() { return 4; }
+ static inline int tagOffset() { return 0; }
+ Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }
+ Q_ALWAYS_INLINE quint32 tag() const { return _val & quint64(~quint32(0)); }
+ Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; }
+#endif
+
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); }
+#else // !QV4_USE_64_BIT_VALUE_ENCODING
+ Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; }
+ Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); }
#endif
- };
- };
+
+ Q_ALWAYS_INLINE int int_32() const { int i; quint32 v = value(); memcpy(&i, &v, 4); return i; }
+ Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); }
+ Q_ALWAYS_INLINE uint uint_32() const { return value(); }
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
enum Masks {
@@ -173,9 +149,9 @@ struct Q_QML_PRIVATE_EXPORT Value
};
enum ValueTypeInternal {
- _Null_Type = Null_Type | ConvertibleToInt,
- _Boolean_Type = Boolean_Type | ConvertibleToInt,
- _Integer_Type = Integer_Type | ConvertibleToInt,
+ Null_Type_Internal = Null_Type | ConvertibleToInt,
+ Boolean_Type_Internal = Boolean_Type | ConvertibleToInt,
+ Integer_Type_Internal = Integer_Type | ConvertibleToInt,
};
#else
@@ -213,134 +189,134 @@ struct Q_QML_PRIVATE_EXPORT Value
enum ValueTypeInternal {
- _Null_Type = Null_Type,
- _Boolean_Type = Boolean_Type,
- _Integer_Type = Integer_Type
+ Null_Type_Internal = Null_Type,
+ Boolean_Type_Internal = Boolean_Type,
+ Integer_Type_Internal = Integer_Type
};
#endif
inline unsigned type() const {
- return tag & Type_Mask;
+ return tag() & Type_Mask;
}
// used internally in property
- inline bool isEmpty() const { return tag == Empty_Type; }
+ inline bool isEmpty() const { return tag() == Empty_Type; }
- inline bool isUndefined() const { return tag == Undefined_Type; }
- inline bool isNull() const { return tag == _Null_Type; }
- inline bool isBoolean() const { return tag == _Boolean_Type; }
+ inline bool isUndefined() const { return tag() == Undefined_Type; }
+ inline bool isNull() const { return tag() == Null_Type_Internal; }
+ inline bool isBoolean() const { return tag ()== Boolean_Type_Internal; }
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
- inline bool isDouble() const { return (val >> IsDouble_Shift); }
- inline bool isNumber() const { return (val >> IsNumber_Shift); }
- inline bool isManaged() const { return !(val >> IsManaged_Shift); }
- inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
- inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
+ inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; }
+ inline bool isDouble() const { return (_val >> IsDouble_Shift); }
+ inline bool isNumber() const { return (_val >> IsNumber_Shift); }
+ inline bool isManaged() const { return !(_val >> IsManaged_Shift); }
+ inline bool isNullOrUndefined() const { return ((_val >> IsManaged_Shift) & ~2) == 1; }
+ inline bool integerCompatible() const { return ((_val >> IsConvertibleToInt_Shift) & ~2) == 1; }
static inline bool integerCompatible(Value a, Value b) {
return a.integerCompatible() && b.integerCompatible();
}
static inline bool bothDouble(Value a, Value b) {
return a.isDouble() && b.isDouble();
}
- double doubleValue() const {
- Q_ASSERT(isDouble());
- union {
- quint64 i;
- double d;
- } v;
- v.i = val ^ NaNEncodeMask;
- return v.d;
- }
- void setDouble(double d) {
- union {
- quint64 i;
- double d;
- } v;
- v.d = d;
- val = v.i ^ NaNEncodeMask;
- Q_ASSERT(isDouble());
- }
- inline bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
+ inline bool isNaN() const { return (tag() & 0x7fff8000) == 0x00078000; }
#else
- inline bool isInteger() const { return tag == _Integer_Type; }
- inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isManaged() const { return tag == Managed_Type; }
- inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
- inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ inline bool isInteger() const { return tag() == Integer_Type_Internal; }
+ inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isNumber() const { return tag() == Integer_Type_Internal || (tag() & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isManaged() const { return tag() == Managed_Type; }
+ inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; }
+ inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; }
static inline bool integerCompatible(Value a, Value b) {
- return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
+ return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt;
}
static inline bool bothDouble(Value a, Value b) {
- return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ return ((a.tag() | b.tag()) & NotDouble_Mask) != NotDouble_Mask;
}
- double doubleValue() const { Q_ASSERT(isDouble()); return dbl; }
- void setDouble(double d) { dbl = d; Q_ASSERT(isDouble()); }
- inline bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+ inline bool isNaN() const { return (tag() & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
#endif
+ Q_ALWAYS_INLINE double doubleValue() const {
+ Q_ASSERT(isDouble());
+ double d;
+ quint64 v = _val;
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ v ^= NaNEncodeMask;
+#endif
+ memcpy(&d, &v, 8);
+ return d;
+ }
+ Q_ALWAYS_INLINE void setDouble(double d) {
+ memcpy(&_val, &d, 8);
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ _val ^= NaNEncodeMask;
+#endif
+ Q_ASSERT(isDouble());
+ }
inline bool isString() const;
inline bool isObject() const;
inline bool isInt32() {
- if (tag == _Integer_Type)
+ if (tag() == Integer_Type_Internal)
return true;
if (isDouble()) {
double d = doubleValue();
int i = (int)d;
if (i == d) {
- int_32 = i;
- tag = _Integer_Type;
+ setInt_32(i);
+ setTag(Integer_Type_Internal);
return true;
}
}
return false;
}
double asDouble() const {
- if (tag == _Integer_Type)
- return int_32;
+ if (tag() == Integer_Type_Internal)
+ return int_32();
return doubleValue();
}
bool booleanValue() const {
- return int_32;
+ return int_32();
}
int integerValue() const {
- return int_32;
+ return int_32();
}
- String *stringValue() const {
- return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE String *stringValue() const {
+ return m() ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
}
- Object *objectValue() const {
- return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Object *objectValue() const {
+ return m() ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
}
- Managed *managed() const {
- return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
+ Q_ALWAYS_INLINE Managed *managed() const {
+ return m() ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
}
- Heap::Base *heapObject() const {
- return m;
+ Q_ALWAYS_INLINE Heap::Base *heapObject() const {
+ return m();
}
- quint64 rawValue() const {
- return val;
+ Q_ALWAYS_INLINE quint64 &rawValueRef() {
+ return _val;
+ }
+ Q_ALWAYS_INLINE quint64 rawValue() const {
+ return _val;
}
+ Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
static inline Value fromHeapObject(Heap::Base *m)
{
Value v;
- v.m = m;
+ v.setRawValue(0);
+ v.setM(m);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- v.tag = Managed_Type;
+ v.setTag(Managed_Type);
#endif
return v;
}
- static inline Value fromManaged(Managed *m);
-
int toUInt16() const;
inline int toInt32() const;
inline unsigned int toUInt32() const;
- inline bool toBoolean() const;
+ bool toBoolean() const;
double toInteger() const;
inline double toNumber() const;
double toNumberImpl() const;
@@ -353,21 +329,32 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool tryIntegerConversion() {
bool b = integerCompatible();
if (b)
- tag = _Integer_Type;
+ setTag(Integer_Type_Internal);
return b;
}
- inline String *asString() const;
- inline Managed *asManaged() const;
- inline Object *asObject() const;
- inline FunctionObject *asFunctionObject() const;
- inline NumberObject *asNumberObject() const;
- inline StringObject *asStringObject() const;
- inline DateObject *asDateObject() const;
- inline ArrayObject *asArrayObject() const;
- inline ErrorObject *asErrorObject() const;
+ template <typename T>
+ const T *as() const {
+ if (!m() || !isManaged())
+ return 0;
+
+ Q_ASSERT(m()->vtable());
+#if !defined(QT_NO_QOBJECT_CHECK)
+ static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
+#endif
+ const VTable *vt = m()->vtable();
+ while (vt) {
+ if (vt == T::staticVTable())
+ return static_cast<const T *>(this);
+ vt = vt->parent;
+ }
+ return 0;
+ }
+ template <typename T>
+ T *as() {
+ return const_cast<T *>(const_cast<const Value *>(this)->as<T>());
+ }
- template<typename T> inline T *as() const;
template<typename T> inline T *cast() {
return static_cast<T *>(managed());
}
@@ -376,26 +363,32 @@ struct Q_QML_PRIVATE_EXPORT Value
}
inline uint asArrayIndex() const;
- inline uint asArrayLength(bool *ok) const;
+#ifndef V4_BOOTSTRAP
+ uint asArrayLength(bool *ok) const;
+#endif
- ReturnedValue asReturnedValue() const { return val; }
- static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
+ ReturnedValue asReturnedValue() const { return _val; }
+ static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
// Section 9.12
bool sameValue(Value other) const;
- inline void mark(ExecutionEngine *e) const;
+ inline void mark(ExecutionEngine *e);
Value &operator =(const ScopedValue &v);
- Value &operator=(ReturnedValue v) { val = v; return *this; }
+ Value &operator=(ReturnedValue v) { _val = v; return *this; }
Value &operator=(Managed *m) {
- val = Value::fromManaged(m).val;
+ if (!m) {
+ setTagValue(Undefined_Type, 0);
+ } else {
+ _val = reinterpret_cast<Value *>(m)->_val;
+ }
return *this;
}
Value &operator=(Heap::Base *o) {
- m = o;
+ setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ setTag(Managed_Type);
#endif
return *this;
}
@@ -403,18 +396,69 @@ struct Q_QML_PRIVATE_EXPORT Value
template<typename T>
Value &operator=(const Scoped<T> &t);
Value &operator=(const Value &v) {
- val = v.val;
+ _val = v._val;
return *this;
}
};
-inline Managed *Value::asManaged() const
+inline bool Value::isString() const
{
- if (isManaged())
- return managed();
- return 0;
+ if (!isManaged())
+ return false;
+ return m() && m()->vtable()->isString;
+}
+inline bool Value::isObject() const
+{
+ if (!isManaged())
+ return false;
+ return m() && m()->vtable()->isObject;
}
+inline bool Value::isPrimitive() const
+{
+ return !isObject();
+}
+
+inline double Value::toNumber() const
+{
+ if (isInteger())
+ return int_32();
+ if (isDouble())
+ return doubleValue();
+ return toNumberImpl();
+}
+
+
+#ifndef V4_BOOTSTRAP
+inline uint Value::asArrayIndex() const
+{
+#ifdef QV4_USE_64_BIT_VALUE_ENCODING
+ if (!isNumber())
+ return UINT_MAX;
+ if (isInteger())
+ return int_32() >= 0 ? (uint)int_32() : UINT_MAX;
+#else
+ if (isInteger() && int_32() >= 0)
+ return (uint)int_32();
+ if (!isDouble())
+ return UINT_MAX;
+#endif
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d)
+ return UINT_MAX;
+ return idx;
+}
+#endif
+
+inline
+ReturnedValue Heap::Base::asReturnedValue() const
+{
+ return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
+}
+
+
+
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
inline static Primitive emptyValue();
@@ -437,10 +481,11 @@ inline Primitive Primitive::undefinedValue()
{
Primitive v;
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- v.val = quint64(Undefined_Type) << Tag_Shift;
+ v.setRawValue(quint64(Undefined_Type) << Tag_Shift);
#else
- v.tag = Undefined_Type;
- v.int_32 = 0;
+ v.setRawValue(0);
+ v.setTag(Undefined_Type);
+ v.setValue(0);
#endif
return v;
}
@@ -448,66 +493,81 @@ inline Primitive Primitive::undefinedValue()
inline Primitive Primitive::emptyValue()
{
Primitive v;
- v.tag = Value::Empty_Type;
- v.uint_32 = 0;
+ v.setTagValue(Value::Empty_Type, 0);
return v;
}
-template <typename T>
-struct TypedValue : public Value
+inline Primitive Primitive::nullValue()
{
- template<typename X>
- TypedValue &operator =(X *x) {
- m = x;
+ Primitive v;
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
- tag = Managed_Type;
+ v.setRawValue(quint64(Null_Type_Internal) << Tag_Shift);
+#else
+ v.setTagValue(Null_Type_Internal, 0);
#endif
- return *this;
- }
- TypedValue &operator =(T *t);
- TypedValue &operator =(const Scoped<T> &v);
-// TypedValue &operator =(const ManagedRef<T> &v);
-
- TypedValue &operator =(const TypedValue<T> &t);
+ return v;
+}
- bool operator!() const { return !managed(); }
+inline Primitive Primitive::fromBoolean(bool b)
+{
+ Primitive v;
+ v.setTagValue(Boolean_Type_Internal, b);
+ return v;
+}
- operator T *() { return static_cast<T *>(managed()); }
- T *operator->() { return static_cast<T *>(managed()); }
- const T *operator->() const { return static_cast<T *>(managed()); }
- T *getPointer() const { return static_cast<T *>(managed()); }
+inline Primitive Primitive::fromDouble(double d)
+{
+ Primitive v;
+ v.setDouble(d);
+ return v;
+}
- void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
-};
-typedef TypedValue<String> StringValue;
+inline Primitive Primitive::fromInt32(int i)
+{
+ Primitive v;
+ v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32(i);
+ return v;
+}
+inline Primitive Primitive::fromUInt32(uint i)
+{
+ Primitive v;
+ if (i < INT_MAX) {
+ v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
+ v.setInt_32((int)i);
+ } else {
+ v.setDouble(i);
+ }
+ return v;
+}
struct Encode {
static ReturnedValue undefined() {
return quint64(Value::Undefined_Type) << Value::Tag_Shift;
}
static ReturnedValue null() {
- return quint64(Value::_Null_Type) << Value::Tag_Shift;
+ return quint64(Value::Null_Type_Internal) << Value::Tag_Shift;
}
Encode(bool b) {
- val = (quint64(Value::_Boolean_Type) << Value::Tag_Shift) | (uint)b;
+ val = (quint64(Value::Boolean_Type_Internal) << Value::Tag_Shift) | (uint)b;
}
Encode(double d) {
Value v;
v.setDouble(d);
- val = v.val;
+ val = v.rawValue();
}
Encode(int i) {
- val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
+ val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | (uint)i;
}
Encode(uint i) {
if (i <= INT_MAX) {
- val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | i;
+ val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | i;
} else {
Value v;
v.setDouble(i);
- val = v.val;
+ val = v.rawValue();
}
}
Encode(ReturnedValue v) {
@@ -527,21 +587,29 @@ private:
Encode(void *);
};
-inline
-ReturnedValue Heap::Base::asReturnedValue() const
+template<typename T>
+ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
+
+inline int Value::toInt32() const
{
- return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
-}
+ if (isInteger())
+ return int_32();
+ double d = isNumber() ? doubleValue() : toNumberImpl();
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
-template<typename T>
-T *value_cast(const Value &v)
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Primitive::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
{
- return v.as<T>();
+ return (unsigned int)toInt32();
}
-template<typename T>
-ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
}
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 966f83acef..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.asObject())
+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
@@ -96,8 +99,8 @@ void VariantPrototype::init()
{
defineDefaultProperty(QStringLiteral("preserve"), method_preserve, 0);
defineDefaultProperty(QStringLiteral("destroy"), method_destroy, 0);
- defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
- defineDefaultProperty(engine()->id_toString, method_toString, 0);
+ defineDefaultProperty(engine()->id_valueOf(), method_valueOf, 0);
+ defineDefaultProperty(engine()->id_toString(), method_toString, 0);
}
QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
@@ -129,7 +132,7 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
return Encode::undefined();
QString result = o->d()->data.toString();
if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String))
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
+ result = QStringLiteral("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
return Encode(ctx->d()->engine->newString(result));
}
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 2b48412c4d..4680912354 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -49,7 +49,7 @@
#include <QtQml/qqmllist.h>
#include <QtCore/qvariant.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
QT_BEGIN_NAMESPACE
@@ -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 390bbf5ee3..024a72bde2 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -37,13 +37,14 @@
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
-#include <private/qv4value_inl_p.h>
+#include <private/qv4value_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4function_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4math_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4lookup_p.h>
+#include <private/qv4string_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -374,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);
@@ -512,6 +513,28 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
+ MOTH_BEGIN_INSTR(StoreScopeObjectProperty)
+ Runtime::setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(StoreContextObjectProperty)
+ Runtime::setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source));
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(StoreContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex));
+ MOTH_END_INSTR(LoadContextObjectProperty)
+
+ MOTH_BEGIN_INSTR(LoadIdObject)
+ STOREVALUE(instr.result, Runtime::getQmlIdObject(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(LoadIdObject)
+
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
MOTH_END_INSTR(LoadAttachedQObjectProperty)
@@ -565,6 +588,26 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData));
MOTH_END_INSTR(CallPropertyLookup)
+ MOTH_BEGIN_INSTR(CallScopeObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(CallContextObjectProperty)
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = QV4::Value::Integer_Type;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ STOREVALUE(instr.result, Runtime::callQmlContextObjectProperty(engine, instr.index, callData));
+ MOTH_END_INSTR(CallContextObjectProperty)
+
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
@@ -607,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)
@@ -641,6 +684,14 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
STOREVALUE(instr.result, Runtime::deleteName(engine, instr.name));
MOTH_END_INSTR(CallBuiltinDeleteName)
+ MOTH_BEGIN_INSTR(CallBuiltinTypeofScopeObjectProperty)
+ STOREVALUE(instr.result, Runtime::typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(CallBuiltinTypeofMember)
+
+ MOTH_BEGIN_INSTR(CallBuiltinTypeofContextObjectProperty)
+ STOREVALUE(instr.result, Runtime::typeofContextObjectProperty(engine, VALUE(instr.base), instr.index));
+ MOTH_END_INSTR(CallBuiltinTypeofMember)
+
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
STOREVALUE(instr.result, Runtime::typeofMember(engine, VALUE(instr.base), instr.member));
MOTH_END_INSTR(CallBuiltinTypeofMember)
@@ -846,7 +897,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();
@@ -855,31 +906,23 @@ 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(Debug)
+ MOTH_END_INSTR(Line)
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->thisObject();
MOTH_END_INSTR(LoadThis)
- MOTH_BEGIN_INSTR(LoadQmlIdArray)
- VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadQmlIdArray)
+ MOTH_BEGIN_INSTR(LoadQmlContext)
+ VALUE(instr.result) = Runtime::getQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
+ MOTH_END_INSTR(LoadQmlContext)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
- MOTH_BEGIN_INSTR(LoadQmlContextObject)
- VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadContextObject)
-
- MOTH_BEGIN_INSTR(LoadQmlScopeObject)
- VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(LoadScopeObject)
-
MOTH_BEGIN_INSTR(LoadQmlSingleton)
VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
MOTH_END_INSTR(LoadQmlSingleton)
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 55cac75a66..c0421022d2 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -34,6 +34,17 @@
#ifndef QV4VME_MOTH_P_H
#define QV4VME_MOTH_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qv4runtime_p.h>
#include <private/qv4instr_moth_p.h>