aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/jsruntime.pri13
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp4
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h4
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp45
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h9
-rw-r--r--src/qml/jsruntime/qv4context.cpp2
-rw-r--r--src/qml/jsruntime/qv4context_p.h10
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp6
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp84
-rw-r--r--src/qml/jsruntime/qv4engine_p.h25
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h3
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4executableallocator.cpp6
-rw-r--r--src/qml/jsruntime/qv4executableallocator_p.h18
-rw-r--r--src/qml/jsruntime/qv4function_p.h2
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp27
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h47
-rw-r--r--src/qml/jsruntime/qv4global_p.h8
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp26
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h104
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp4
-rw-r--r--src/qml/jsruntime/qv4include.cpp30
-rw-r--r--src/qml/jsruntime/qv4include_p.h2
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp19
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h8
-rw-r--r--src/qml/jsruntime/qv4jscall_p.h4
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp20
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4managed.cpp8
-rw-r--r--src/qml/jsruntime/qv4managed_p.h2
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h6
-rw-r--r--src/qml/jsruntime/qv4object.cpp76
-rw-r--r--src/qml/jsruntime/qv4object_p.h32
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp8
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h4
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp6
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp50
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h24
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp3
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h40
-rw-r--r--src/qml/jsruntime/qv4property_p.h4
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp22
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp131
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h8
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp10
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h4
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp42
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp53
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtimecodegen.cpp7
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h6
-rw-r--r--src/qml/jsruntime/qv4script.cpp49
-rw-r--r--src/qml/jsruntime/qv4script_p.h11
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp45
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp42
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h8
-rw-r--r--src/qml/jsruntime/qv4string.cpp106
-rw-r--r--src/qml/jsruntime/qv4string_p.h88
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp25
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp10
-rw-r--r--src/qml/jsruntime/qv4value_p.h101
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp18
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp40
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h2
72 files changed, 910 insertions, 751 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 519c87d0c4..4bc877bd9d 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -41,7 +41,8 @@ SOURCES += \
$$PWD/qv4qobjectwrapper.cpp \
$$PWD/qv4arraybuffer.cpp \
$$PWD/qv4typedarray.cpp \
- $$PWD/qv4dataview.cpp
+ $$PWD/qv4dataview.cpp \
+ $$PWD/qv4vme_moth.cpp
qtConfig(qml-debug): SOURCES += $$PWD/qv4profiling.cpp
@@ -94,14 +95,8 @@ HEADERS += \
$$PWD/qv4profiling_p.h \
$$PWD/qv4arraybuffer_p.h \
$$PWD/qv4typedarray_p.h \
- $$PWD/qv4dataview_p.h
-
-qtConfig(qml-interpreter) {
- HEADERS += \
- $$PWD/qv4vme_moth_p.h
- SOURCES += \
- $$PWD/qv4vme_moth.cpp
-}
+ $$PWD/qv4dataview_p.h \
+ $$PWD/qv4vme_moth_p.h
}
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index f7b9e8acef..c4eddb6b2a 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -96,7 +96,7 @@ void Heap::ArrayBuffer::init(size_t length)
Object::init();
data = QTypedArrayData<char>::allocate(length + 1);
if (!data) {
- data = 0;
+ data = nullptr;
internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
return;
}
@@ -152,7 +152,7 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
ctor->defineReadonlyProperty(engine->id_prototype(), (o = this));
ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
defineDefaultProperty(engine->id_constructor(), (o = ctor));
- defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
defineDefaultProperty(QStringLiteral("toString"), method_toString, 0);
}
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index e236a23d1f..59e78ee85f 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -93,8 +93,8 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
- char *data() { detach(); return d()->data ? d()->data->data() : 0; }
- const char *constData() { detach(); return d()->data ? d()->data->data() : 0; }
+ char *data() { detach(); return d()->data ? d()->data->data() : nullptr; }
+ const char *constData() { detach(); return d()->data ? d()->data->data() : nullptr; }
private:
void detach();
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 390840fb1e..30c8527f21 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -50,7 +50,7 @@ using namespace QV4;
QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON
const QV4::VTable QV4::ArrayData::static_vtbl = {
- 0,
+ nullptr,
0,
0,
QV4::ArrayData::IsExecutionContext,
@@ -69,7 +69,7 @@ const QV4::VTable QV4::ArrayData::static_vtbl = {
const ArrayVTable SimpleArrayData::static_vtbl =
{
- DEFINE_MANAGED_VTABLE_INT(SimpleArrayData, 0),
+ DEFINE_MANAGED_VTABLE_INT(SimpleArrayData, nullptr),
Heap::ArrayData::Simple,
SimpleArrayData::reallocate,
SimpleArrayData::get,
@@ -85,7 +85,7 @@ const ArrayVTable SimpleArrayData::static_vtbl =
const ArrayVTable SparseArrayData::static_vtbl =
{
- DEFINE_MANAGED_VTABLE_INT(SparseArrayData, 0),
+ DEFINE_MANAGED_VTABLE_INT(SparseArrayData, nullptr),
Heap::ArrayData::Sparse,
SparseArrayData::reallocate,
SparseArrayData::get,
@@ -170,7 +170,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
newData->setType(newType);
if (d)
newData->d()->needsMark = d->d()->needsMark;
- newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->values.values + alloc) : 0);
+ newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->values.values + alloc) : nullptr);
o->setArrayData(newData);
if (d) {
@@ -203,12 +203,11 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
if (d && d->type() == Heap::ArrayData::Sparse) {
Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
sparse->sparse = old->sparse;
- old->sparse = 0;
- sparse->freeList = old->freeList;
- lastFree = &sparse->freeList;
+ old->sparse = nullptr;
+ lastFree = &sparse->sparse->freeList;
} else {
sparse->sparse = new SparseArray;
- lastFree = &sparse->freeList;
+ lastFree = &sparse->sparse->freeList;
storeValue(lastFree, 0);
for (uint i = 0; i < toCopy; ++i) {
if (!sparse->values[i].isEmpty()) {
@@ -228,10 +227,10 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
sparse->values.values[i].setEmpty();
lastFree = &sparse->values.values[i].rawValueRef();
}
- storeValue(lastFree, UINT_MAX);
}
+ storeValue(lastFree, UINT_MAX);
- Q_ASSERT(Value::fromReturnedValue(sparse->freeList).isEmpty());
+ Q_ASSERT(Value::fromReturnedValue(sparse->sparse->freeList).isEmpty());
// ### Could explicitly free the old data
}
@@ -373,12 +372,12 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx)
Value *v = d->values.values + 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].setEmpty(Value::fromReturnedValue(d->freeList).emptyValue());
+ v[1].setEmpty(Value::fromReturnedValue(d->sparse->freeList).emptyValue());
v[0].setEmpty(idx + 1);
} else {
- v->setEmpty(Value::fromReturnedValue(d->freeList).emptyValue());
+ v->setEmpty(Value::fromReturnedValue(d->sparse->freeList).emptyValue());
}
- d->freeList = Primitive::emptyValue(idx).asReturnedValue();
+ d->sparse->freeList = Primitive::emptyValue(idx).asReturnedValue();
if (d->attrs)
d->attrs[idx].clear();
}
@@ -395,12 +394,12 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (doubleSlot) {
- ReturnedValue *last = &dd->freeList;
+ ReturnedValue *last = &dd->sparse->freeList;
while (1) {
if (Value::fromReturnedValue(*last).value() == UINT_MAX) {
reallocate(o, dd->values.alloc + 2, true);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
- last = &dd->freeList;
+ last = &dd->sparse->freeList;
Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX);
}
@@ -417,14 +416,14 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
last = &dd->values.values[Value::fromReturnedValue(*last).value()].rawValueRef();
}
} else {
- if (Value::fromReturnedValue(dd->freeList).value() == UINT_MAX) {
+ if (Value::fromReturnedValue(dd->sparse->freeList).value() == UINT_MAX) {
reallocate(o, dd->values.alloc + 1, false);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- uint idx = Value::fromReturnedValue(dd->freeList).value();
+ uint idx = Value::fromReturnedValue(dd->sparse->freeList).value();
Q_ASSERT(idx != UINT_MAX);
- dd->freeList = dd->values[idx].asReturnedValue();
- Q_ASSERT(Value::fromReturnedValue(dd->freeList).isEmpty());
+ dd->sparse->freeList = dd->values[idx].asReturnedValue();
+ Q_ASSERT(Value::fromReturnedValue(dd->sparse->freeList).isEmpty());
if (dd->attrs)
dd->attrs[idx] = Attr_Data;
return idx;
@@ -479,14 +478,14 @@ bool SparseArrayData::del(Object *o, uint index)
if (isAccessor) {
// free up both indices
- dd->values.values[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
+ dd->values.values[pidx + 1].setEmpty(Value::fromReturnedValue(dd->sparse->freeList).emptyValue());
dd->values.values[pidx].setEmpty(pidx + 1);
} else {
Q_ASSERT(dd->type == Heap::ArrayData::Sparse);
- dd->values.values[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue());
+ dd->values.values[pidx].setEmpty(Value::fromReturnedValue(dd->sparse->freeList).emptyValue());
}
- dd->freeList = Primitive::emptyValue(pidx).asReturnedValue();
+ dd->sparse->freeList = Primitive::emptyValue(pidx).asReturnedValue();
dd->sparse->erase(n);
return true;
}
@@ -780,7 +779,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
if (!sparse->sparse()->nEntries())
return;
- thisObject->setArrayData(0);
+ thisObject->setArrayData(nullptr);
ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>();
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index db9db5a220..9356670b6d 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -95,7 +95,6 @@ namespace Heap {
Member(class, NoMark, ushort, needsMark) \
Member(class, NoMark, uint, offset) \
Member(class, NoMark, PropertyAttributes *, attrs) \
- Member(class, NoMark, ReturnedValue, freeList) \
Member(class, NoMark, SparseArray *, sparse) \
Member(class, ValueArray, ValueArray, values)
@@ -142,7 +141,7 @@ DECLARE_HEAP_OBJECT(ArrayData, Base) {
uint mappedIndex(uint index) const;
};
-V4_ASSERT_IS_TRIVIAL(ArrayData)
+Q_STATIC_ASSERT(std::is_trivial< ArrayData >::value);
struct SimpleArrayData : public ArrayData {
uint mappedIndex(uint index) const { index += offset; if (index >= values.alloc) index -= values.alloc; return index; }
@@ -157,7 +156,7 @@ struct SimpleArrayData : public ArrayData {
return attrs ? attrs[i] : Attr_Data;
}
};
-V4_ASSERT_IS_TRIVIAL(SimpleArrayData)
+Q_STATIC_ASSERT(std::is_trivial< SimpleArrayData >::value);
struct SparseArrayData : public ArrayData {
void destroy() {
@@ -264,8 +263,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
V4_INTERNALCLASS(SparseArrayData)
V4_NEEDS_DESTROY
- ReturnedValue &freeList() { return d()->freeList; }
- ReturnedValue freeList() const { return d()->freeList; }
SparseArray *sparse() const { return d()->sparse; }
void setSparse(SparseArray *s) { d()->sparse = s; }
@@ -334,7 +331,7 @@ ArrayData::Index ArrayData::getValueOrSetter(uint index, PropertyAttributes *att
uint idx = mappedIndex(index);
if (idx == UINT_MAX) {
*attrs = Attr_Invalid;
- return { 0, 0 };
+ return { nullptr, 0 };
}
*attrs = attributes(index);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 00d816fe91..020e519e74 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -302,7 +302,7 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
{
- base->setM(0);
+ base->setM(nullptr);
name->makeIdentifier();
Heap::ExecutionContext *ctx = d();
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 4efd0bc899..512bfa06d8 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -143,7 +143,7 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
quint8 padding_[4];
#endif
};
-V4_ASSERT_IS_TRIVIAL(ExecutionContext)
+Q_STATIC_ASSERT(std::is_trivial< ExecutionContext >::value);
Q_STATIC_ASSERT(sizeof(ExecutionContext) == sizeof(Base) + sizeof(ExecutionContextData) + QT_POINTER_SIZE);
Q_STATIC_ASSERT(std::is_standard_layout<ExecutionContextData>::value);
@@ -170,7 +170,7 @@ DECLARE_HEAP_OBJECT(CallContext, ExecutionContext) {
}
void setArg(uint index, Value v);
};
-V4_ASSERT_IS_TRIVIAL(CallContext)
+Q_STATIC_ASSERT(std::is_trivial< CallContext >::value);
Q_STATIC_ASSERT(std::is_standard_layout<CallContextData>::value);
Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0);
//### The following size check fails on Win8. With the ValueArray at the end of the
@@ -190,7 +190,7 @@ DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) {
void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
};
-V4_ASSERT_IS_TRIVIAL(CatchContext)
+Q_STATIC_ASSERT(std::is_trivial< CatchContext >::value);
}
@@ -246,12 +246,12 @@ struct CatchContext : public ExecutionContext
inline CallContext *ExecutionContext::asCallContext()
{
- return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<CallContext *>(this) : 0;
+ return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<CallContext *>(this) : nullptr;
}
inline const CallContext *ExecutionContext::asCallContext() const
{
- return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<const CallContext *>(this) : 0;
+ return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<const CallContext *>(this) : nullptr;
}
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index 397ef1cfec..d894d909ff 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -88,9 +88,9 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *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);
+ defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, nullptr);
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
+ defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, nullptr);
defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 0);
defineDefaultProperty(QStringLiteral("getUint8"), method_getChar<unsigned char>, 0);
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index b8392d27e9..bc9b3013d1 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -328,7 +328,7 @@ static inline double DaylightSavingTA(double t) // t is a UTC time
static inline double DaylightSavingTA(double t)
{
struct tm tmtm;
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#if defined(Q_CC_MSVC)
__time64_t tt = (__time64_t)(t / msPerSecond);
// _localtime_64_s returns non-zero on failure
if (_localtime64_s(&tmtm, &tt) != 0)
@@ -854,7 +854,7 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
ScopedString us(scope, engine->newIdentifier(toUtcString));
ScopedString gs(scope, engine->newIdentifier(toGmtString));
ExecutionContext *global = engine->rootContext();
- ScopedFunctionObject toUtcGmtStringFn(scope, BuiltinFunction::create(global, us, method_toUTCString));
+ ScopedFunctionObject toUtcGmtStringFn(scope, FunctionObject::createBuiltinFunction(global, us, method_toUTCString));
toUtcGmtStringFn->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
defineDefaultProperty(us, toUtcGmtStringFn);
defineDefaultProperty(gs, toUtcGmtStringFn);
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index a4ab0a27ed..2b9a580288 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -101,7 +101,7 @@ struct DateObject: Object {
template<>
inline const DateObject *Value::as() const {
- return isManaged() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : 0;
+ return isManaged() && m()->vtable()->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : nullptr;
}
struct DateCtor: FunctionObject
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index 61a55964ab..9b41bb6e7a 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -78,7 +78,7 @@ class Q_QML_EXPORT Debugger : public QObject
Q_OBJECT
public:
- virtual ~Debugger() {}
+ ~Debugger() override {}
virtual bool pauseAtNextOpportunity() const = 0;
virtual void maybeBreakAtInstruction() = 0;
virtual void enteringFunction() = 0;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index c57f39f61c..5f59e1e809 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -101,7 +101,7 @@ using namespace QV4;
static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
-ReturnedValue throwTypeError(const BuiltinFunction *b, CallData *)
+ReturnedValue throwTypeError(const FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
{
return b->engine()->throwTypeError();
}
@@ -127,13 +127,16 @@ ExecutionEngine::ExecutionEngine()
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, gcStack(new WTF::PageAllocation)
- , globalCode(0)
- , v8Engine(0)
- , argumentsAccessors(0)
+ , globalCode(nullptr)
+ , v8Engine(nullptr)
+ , argumentsAccessors(nullptr)
, nArgumentsAccessors(0)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
- , regExpCache(0)
- , m_multiplyWrappedQObjects(0)
+ , regExpCache(nullptr)
+ , m_multiplyWrappedQObjects(nullptr)
+#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+ , m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
+#endif
{
memoryManager = new QV4::MemoryManager(this);
@@ -168,6 +171,15 @@ ExecutionEngine::ExecutionEngine()
/* writable */ true, /* executable */ false,
/* includesGuardPages */ true);
+ {
+ bool ok = false;
+ jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
+ if (!ok)
+ jitCallCountThreshold = 3;
+ if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
+ jitCallCountThreshold = std::numeric_limits<int>::max();
+ }
+
exceptionValue = jsAlloca(1);
globalObject = static_cast<Object *>(jsAlloca(1));
jsObjects = jsAlloca(NJSObjects);
@@ -188,6 +200,7 @@ ExecutionEngine::ExecutionEngine()
internalClasses[Class_SimpleArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
internalClasses[Class_SparseArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
internalClasses[Class_ExecutionContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
+ internalClasses[Class_QmlContext] = internalClasses[EngineBase::Class_ExecutionContext]->changeVTable(QV4::QmlContext::staticVTable());
internalClasses[Class_CallContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
jsStrings[String_Empty] = newIdentifier(QString());
@@ -230,6 +243,7 @@ ExecutionEngine::ExecutionEngine()
InternalClass *ic = internalClasses[Class_Empty]->changeVTable(QV4::Object::staticVTable());
jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic);
internalClasses[Class_Object] = ic->changePrototype(objectPrototype()->d());
+ internalClasses[EngineBase::Class_QmlContextWrapper] = internalClasses[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
Q_ASSERT(ic->prototype);
@@ -275,8 +289,6 @@ ExecutionEngine::ExecutionEngine()
ic = ic->changeVTable(ScriptFunction::staticVTable());
internalClasses[EngineBase::Class_ScriptFunction] = ic->addMember(id_length(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::ScriptFunction::Index_Length);
- internalClasses[EngineBase::Class_BuiltinFunction] = ic->changeVTable(BuiltinFunction::staticVTable());
- Q_ASSERT(index == Heap::ScriptFunction::Index_Length);
internalClasses[EngineBase::Class_ObjectProto] = internalClasses[Class_Object]->addMember(id_constructor(), Attr_NotEnumerable, &index);
Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
@@ -302,7 +314,7 @@ ExecutionEngine::ExecutionEngine()
internalClasses[EngineBase::Class_RegExpExecArray] = ic->addMember(id_input(), Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- ic = newInternalClass(ErrorObject::staticVTable(), 0);
+ ic = newInternalClass(ErrorObject::staticVTable(), nullptr);
ic = ic->addMember((str = newIdentifier(QStringLiteral("stack"))), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
Q_ASSERT(index == ErrorObject::Index_Stack);
ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName"))), Attr_Data|Attr_NotEnumerable, &index);
@@ -320,7 +332,7 @@ ExecutionEngine::ExecutionEngine()
internalClasses[EngineBase::Class_ErrorProto] = ic->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);
+ jsObjects[GetStack_Function] = FunctionObject::createBuiltinFunction(rootContext(), str = newIdentifier(QStringLiteral("stack")), ErrorObject::method_get_stack);
getStackFunction()->defineReadonlyProperty(id_length(), Primitive::fromInt32(0));
jsObjects[ErrorProto] = memoryManager->allocObject<ErrorPrototype>(internalClasses[EngineBase::Class_ErrorProto], objectPrototype());
@@ -384,8 +396,8 @@ ExecutionEngine::ExecutionEngine()
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;
+ jsObjects[ValueTypeProto] = (Heap::Base *) nullptr;
+ jsObjects[SignalHandlerProto] = (Heap::Base *) nullptr;
for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocObject<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
@@ -442,8 +454,8 @@ ExecutionEngine::ExecutionEngine()
ScopedString pi(scope, newIdentifier(piString));
ScopedString pf(scope, newIdentifier(pfString));
ExecutionContext *global = rootContext();
- ScopedFunctionObject parseIntFn(scope, BuiltinFunction::create(global, pi, GlobalFunctions::method_parseInt));
- ScopedFunctionObject parseFloatFn(scope, BuiltinFunction::create(global, pf, GlobalFunctions::method_parseFloat));
+ ScopedFunctionObject parseIntFn(scope, FunctionObject::createBuiltinFunction(global, pi, GlobalFunctions::method_parseInt));
+ ScopedFunctionObject parseFloatFn(scope, FunctionObject::createBuiltinFunction(global, pf, GlobalFunctions::method_parseFloat));
parseIntFn->defineReadonlyConfigurableProperty(id_length(), Primitive::fromInt32(2));
parseFloatFn->defineReadonlyConfigurableProperty(id_length(), Primitive::fromInt32(1));
globalObject->defineDefaultProperty(piString, parseIntFn);
@@ -462,13 +474,13 @@ ExecutionEngine::ExecutionEngine()
globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
ScopedString name(scope, newString(QStringLiteral("thrower")));
- jsObjects[ThrowerObject] = BuiltinFunction::create(global, name, ::throwTypeError);
+ jsObjects[ThrowerObject] = FunctionObject::createBuiltinFunction(global, name, ::throwTypeError);
}
ExecutionEngine::~ExecutionEngine()
{
delete m_multiplyWrappedQObjects;
- m_multiplyWrappedQObjects = 0;
+ m_multiplyWrappedQObjects = nullptr;
delete identifierTable;
delete memoryManager;
@@ -519,7 +531,7 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype)
{
- return internalClasses[EngineBase::Class_Empty]->changeVTable(vtable)->changePrototype(prototype ? prototype->d() : 0);
+ return internalClasses[EngineBase::Class_Empty]->changeVTable(vtable)->changePrototype(prototype ? prototype->d() : nullptr);
}
Heap::Object *ExecutionEngine::newObject()
@@ -721,18 +733,18 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
Heap::QmlContext *ExecutionEngine::qmlContext() const
{
if (!currentStackFrame)
- return 0;
+ return nullptr;
Heap::ExecutionContext *ctx = currentContext()->d();
if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !ctx->outer)
- return 0;
+ return nullptr;
while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext)
ctx = ctx->outer;
Q_ASSERT(ctx);
if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
- return 0;
+ return nullptr;
return static_cast<Heap::QmlContext *>(ctx);
}
@@ -741,7 +753,7 @@ QObject *ExecutionEngine::qmlScopeObject() const
{
Heap::QmlContext *ctx = qmlContext();
if (!ctx)
- return 0;
+ return nullptr;
return ctx->qml()->scopeObject;
}
@@ -771,7 +783,7 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const
{
Heap::QmlContext *ctx = qmlContext();
if (!ctx)
- return 0;
+ return nullptr;
return ctx->qml()->context->contextData();
}
@@ -868,14 +880,14 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
CppStackFrame *f = currentStackFrame;
while (f) {
if (f->v4Function) {
- base.setUrl(f->v4Function->sourceFile());
+ base = f->v4Function->finalUrl();
break;
}
f = f->parent;
}
if (base.isEmpty() && globalCode)
- base.setUrl(globalCode->sourceFile());
+ base = globalCode->finalUrl();
if (base.isEmpty())
return src;
@@ -898,7 +910,7 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
nArgumentsAccessors = qMax(8, n);
argumentsAccessors = new Property[nArgumentsAccessors];
if (oldAccessors) {
- memcpy(argumentsAccessors, oldAccessors, oldSize*sizeof(Property));
+ memcpy(static_cast<void *>(argumentsAccessors), static_cast<const void *>(oldAccessors), oldSize*sizeof(Property));
delete [] oldAccessors;
}
ExecutionContext *global = rootContext();
@@ -1079,7 +1091,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
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, const QV4::Object *o, V4ObjectSet *visitedObjects = 0);
+static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr);
static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
const QByteArray &targetType,
void **result);
@@ -1093,7 +1105,7 @@ static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &
QVariant ExecutionEngine::toVariant(const Value &value, int typeHint, bool createJSValueForObjects)
{
- return ::toVariant(this, value, typeHint, createJSValueForObjects, 0);
+ return ::toVariant(this, value, typeHint, createJSValueForObjects, nullptr);
}
@@ -1457,7 +1469,7 @@ static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVarian
// Returns the value if conversion succeeded, an empty handle otherwise.
QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
{
- Q_ASSERT(data != 0);
+ Q_ASSERT(data != nullptr);
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
@@ -1545,13 +1557,9 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-bool ExecutionEngine::canJIT()
+ReturnedValue ExecutionEngine::global()
{
-#ifdef V4_ENABLE_JIT
- return true;
-#else
- return false;
-#endif
+ return globalObject->asReturnedValue();
}
// Converts a JS value to a meta-type.
@@ -1734,7 +1742,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
if (QObject *qobject = qtObjectFromJS(this, p))
- canCast = qobject->qt_metacast(className) != 0;
+ canCast = qobject->qt_metacast(className) != nullptr;
}
if (canCast) {
QByteArray varTypeName = QMetaType::typeName(var.userType());
@@ -1748,7 +1756,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
}
}
} else if (value->isNull() && name.endsWith('*')) {
- *reinterpret_cast<void* *>(data) = 0;
+ *reinterpret_cast<void* *>(data) = nullptr;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
*reinterpret_cast<QJSValue*>(data) = QJSValue(this, value->asReturnedValue());
@@ -1776,7 +1784,7 @@ static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &va
static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value)
{
if (!value.isObject())
- return 0;
+ return nullptr;
QV4::Scope scope(engine);
QV4::Scoped<QV4::VariantObject> v(scope, value);
@@ -1789,7 +1797,7 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &v
}
QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, value);
if (!wrapper)
- return 0;
+ return nullptr;
return wrapper->object();
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 346f290feb..5edf89f720 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -56,7 +56,9 @@
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
+
#ifndef V4_BOOTSTRAP
+# include "qv4function_p.h"
# include <private/qv8engine_p.h>
# include <private/qv4compileddata_p.h>
#endif
@@ -85,6 +87,7 @@ namespace CompiledData {
struct CompilationUnit;
}
+struct Function;
struct InternalClass;
struct InternalClassPool;
@@ -365,6 +368,9 @@ public:
// but any time a QObject is wrapped a second time in another engine, we have to do
// bookkeeping.
MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
+#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+ const bool m_canAllocateExecutableMemory;
+#endif
int internalClassIdCount = 0;
@@ -453,7 +459,7 @@ public:
StackTrace exceptionStackTrace;
ReturnedValue throwError(const Value &value);
- ReturnedValue catchException(StackTrace *trace = 0);
+ ReturnedValue catchException(StackTrace *trace = nullptr);
ReturnedValue throwError(const QString &message);
ReturnedValue throwSyntaxError(const QString &message);
@@ -481,13 +487,28 @@ public:
bool checkStackLimits();
- static bool canJIT();
+ bool canJIT(Function *f = nullptr)
+ {
+#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+ if (!m_canAllocateExecutableMemory)
+ return false;
+ if (f)
+ return f->interpreterCallCount >= jitCallCountThreshold;
+ return true;
+#else
+ Q_UNUSED(f);
+ return false;
+#endif
+ }
+
+ QV4::ReturnedValue global();
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
+ int jitCallCountThreshold;
};
// This is a trick to tell the code generators that functions taking a NoThrowContext won't
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index e0f5f3ffb1..59fb4a564a 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -101,7 +101,6 @@ struct Q_QML_EXPORT EngineBase {
Class_FunctionObject,
Class_StringObject,
Class_ScriptFunction,
- Class_BuiltinFunction,
Class_ObjectProto,
Class_RegExp,
Class_RegExpObject,
@@ -111,6 +110,8 @@ struct Q_QML_EXPORT EngineBase {
Class_ErrorObject,
Class_ErrorObjectWithMessage,
Class_ErrorProto,
+ Class_QmlContextWrapper,
+ Class_QmlContext,
NClasses
};
InternalClass *internalClasses[NClasses];
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index a5ee0eb886..6b578e8c38 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -180,7 +180,7 @@ struct ErrorObject: Object {
template<>
inline const ErrorObject *Value::as() const {
- return isManaged() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : 0;
+ return isManaged() && m()->vtable()->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : nullptr;
}
struct EvalErrorObject: ErrorObject {
@@ -322,7 +322,7 @@ struct URIErrorPrototype : ErrorObject
inline SyntaxErrorObject *ErrorObject::asSyntaxError()
{
- return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
+ return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : nullptr;
}
diff --git a/src/qml/jsruntime/qv4executableallocator.cpp b/src/qml/jsruntime/qv4executableallocator.cpp
index 64ac1267ce..6f04a712e6 100644
--- a/src/qml/jsruntime/qv4executableallocator.cpp
+++ b/src/qml/jsruntime/qv4executableallocator.cpp
@@ -159,7 +159,7 @@ ExecutableAllocator::~ExecutableAllocator()
ExecutableAllocator::Allocation *ExecutableAllocator::allocate(size_t size)
{
QMutexLocker locker(&mutex);
- Allocation *allocation = 0;
+ Allocation *allocation = nullptr;
// Code is best aligned to 16-byte boundaries.
size = WTF::roundUpToMultipleOf(16, size);
@@ -217,7 +217,7 @@ void ExecutableAllocator::free(Allocation *allocation)
if (!merged)
freeAllocations.insert(allocation->size, allocation);
- allocation = 0;
+ allocation = nullptr;
if (!chunk->firstAllocation->next) {
freeAllocations.remove(chunk->firstAllocation->size, chunk->firstAllocation);
@@ -235,7 +235,7 @@ ExecutableAllocator::ChunkOfPages *ExecutableAllocator::chunkForAllocation(Alloc
if (it != chunks.begin())
--it;
if (it == chunks.end())
- return 0;
+ return nullptr;
return *it;
}
diff --git a/src/qml/jsruntime/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h
index dad02d9560..19eaed8723 100644
--- a/src/qml/jsruntime/qv4executableallocator_p.h
+++ b/src/qml/jsruntime/qv4executableallocator_p.h
@@ -82,11 +82,8 @@ public:
struct Allocation
{
Allocation()
- : addr(0)
- , size(0)
+ : size(0)
, free(true)
- , next(0)
- , prev(0)
{}
void *start() const;
@@ -103,16 +100,16 @@ public:
bool mergeNext(ExecutableAllocator *allocator);
bool mergePrevious(ExecutableAllocator *allocator);
- quintptr addr;
#ifndef QT_NO_BITFIELDS
+ quintptr addr = 0;
uint size : 31; // More than 2GB of function code? nah :)
uint free : 1;
#else
uint size = 31; // More than 2GB of function code? nah :)
uint free = 1;
#endif
- Allocation *next;
- Allocation *prev;
+ Allocation *next = nullptr;
+ Allocation *prev = nullptr;
};
// for debugging / unit-testing
@@ -122,13 +119,12 @@ public:
struct ChunkOfPages
{
ChunkOfPages()
- : pages(0)
- , firstAllocation(0)
+
{}
~ChunkOfPages();
- WTF::PageAllocation *pages;
- Allocation *firstAllocation;
+ WTF::PageAllocation *pages = nullptr;
+ Allocation *firstAllocation = nullptr;
bool contains(Allocation *alloc) const;
};
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 0e61be5115..4c8c790ca7 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -83,6 +83,7 @@ struct Q_QML_EXPORT Function {
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
uint nFormals;
+ int interpreterCallCount = 0;
bool hasQmlDependencies;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, Code codePtr);
@@ -95,6 +96,7 @@ struct Q_QML_EXPORT Function {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
inline QString sourceFile() const { return compilationUnit->fileName(); }
+ inline QUrl finalUrl() const { return compilationUnit->finalUrl(); }
inline bool usesArgumentsObject() const { return compiledFunction->flags & CompiledData::Function::UsesArgumentsObject; }
inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; }
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 4293d43791..a8c1640767 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -232,7 +232,7 @@ ReturnedValue FunctionCtor::callAsConstructor(const FunctionObject *f, const Val
if (!fe)
return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
- Compiler::Module module(scope.engine->debugger() != 0);
+ Compiler::Module module(scope.engine->debugger() != nullptr);
Compiler::JSUnitGenerator jsGenerator(&module);
RuntimeCodegen cg(scope.engine, &jsGenerator, false);
@@ -351,7 +351,7 @@ ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Valu
return scope.engine->throwTypeError();
ScopedValue boundThis(scope, argc ? argv[0] : Primitive::undefinedValue());
- Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
+ Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)nullptr);
if (argc > 1) {
boundArgs = MemberData::allocate(scope.engine, argc - 1);
boundArgs->d()->values.size = argc - 1;
@@ -430,27 +430,6 @@ InternalClass *ScriptFunction::classForConstructor() const
return ic;
}
-DEFINE_OBJECT_VTABLE(BuiltinFunction);
-
-void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *))
-{
- Heap::FunctionObject::init(scope, name);
- this->code = code;
-}
-
-ReturnedValue BuiltinFunction::callAsConstructor(const QV4::FunctionObject *f, const Value *, int)
-{
- return f->engine()->throwTypeError();
-}
-
-ReturnedValue BuiltinFunction::call(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
-{
- const BuiltinFunction *f = static_cast<const BuiltinFunction *>(fo);
- Scope scope(f->engine());
- JSCallData callData(scope, argc, argv, thisObject);
- return f->d()->code(f, callData.callData());
-}
-
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
DEFINE_OBJECT_VTABLE(BoundFunction);
@@ -461,7 +440,7 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject
Scope s(scope);
Heap::FunctionObject::init(scope, QStringLiteral("__bound function__"));
this->target.set(s.engine, target->d());
- this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : 0);
+ this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : nullptr);
this->boundThis.set(scope->engine(), boundThis);
ScopedObject f(s, this);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index d61006a6b0..d6066ec648 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -61,7 +61,6 @@ struct QQmlSourceLocation;
namespace QV4 {
-struct BuiltinFunction;
struct IndexedBuiltinFunction;
struct JSCallData;
@@ -84,8 +83,8 @@ DECLARE_HEAP_OBJECT(FunctionObject, Object) {
Index_ProtoConstructor = 0
};
- void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(const QV4::FunctionObject *, const Value *thisObject, const Value *argv, int argc));
- void init(QV4::ExecutionContext *scope, QV4::String *name = 0, bool createProto = false);
+ Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(const QV4::FunctionObject *, const Value *thisObject, const Value *argv, int argc));
+ void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr, bool createProto = false);
void init(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false);
void init(QV4::ExecutionContext *scope, const QString &name, bool createProto = false);
void init();
@@ -105,13 +104,8 @@ struct FunctionPrototype : FunctionObject {
void init();
};
-struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
- void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *));
- ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *);
-};
-
-struct IndexedBuiltinFunction : BuiltinFunction {
- inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *));
+struct IndexedBuiltinFunction : FunctionObject {
+ inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(const QV4::FunctionObject *, const Value *, const Value *, int));
uint index;
};
@@ -170,6 +164,11 @@ struct Q_QML_EXPORT FunctionObject: Object {
static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function);
+ static Heap::FunctionObject *createBuiltinFunction(ExecutionContext *scope, String *name,
+ ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc))
+ {
+ return scope->engine()->memoryManager->allocObject<FunctionObject>(scope, name, code);
+ }
bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
bool isBinding() const;
@@ -180,7 +179,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
template<>
inline const FunctionObject *Value::as() const {
- return isManaged() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : 0;
+ return isManaged() && m()->vtable()->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : nullptr;
}
@@ -204,34 +203,16 @@ struct FunctionPrototype: FunctionObject
static ReturnedValue method_bind(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
-struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
- V4_OBJECT2(BuiltinFunction, FunctionObject)
- V4_INTERNALCLASS(BuiltinFunction)
-
- static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(const BuiltinFunction *, CallData *))
- {
- return scope->engine()->memoryManager->allocObject<BuiltinFunction>(scope, name, code);
- }
-
- static Heap::FunctionObject *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc))
- {
- return scope->engine()->memoryManager->allocObject<FunctionObject>(scope, name, code);
- }
-
- static ReturnedValue callAsConstructor(const FunctionObject *, const Value *argv, int argc);
- static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
-};
-
-struct IndexedBuiltinFunction: BuiltinFunction
+struct IndexedBuiltinFunction : FunctionObject
{
- V4_OBJECT2(IndexedBuiltinFunction, BuiltinFunction)
+ V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
};
void Heap::IndexedBuiltinFunction::init(QV4::ExecutionContext *scope, uint index,
- ReturnedValue (*code)(const QV4::BuiltinFunction *, CallData *))
+ ReturnedValue (*code)(const QV4::FunctionObject *, const Value *thisObject, const Value *argv, int argc))
{
Heap::FunctionObject::init(scope);
- this->code = code;
+ this->jsCall = code;
this->index = index;
}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 29eddc864d..382dd9b7e1 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -76,9 +76,6 @@ namespace std {
inline bool isinf(double d) { return !_finite(d) && !_isnan(d); }
inline bool isnan(double d) { return !!_isnan(d); }
inline bool isfinite(double d) { return _finite(d); }
-#if _MSC_VER < 1800
-inline bool signbit(double d) { return _copysign(1.0, d) < 0; }
-#endif
} // namespace std
@@ -95,7 +92,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
&& (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
- && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
+ && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4)
# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
@@ -104,7 +101,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
# define V4_ENABLE_JIT
# endif
#elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8)
-# if defined(Q_OS_LINUX)
+# if defined(Q_OS_LINUX) || defined(Q_OS_QNX)
# define V4_ENABLE_JIT
# endif
//#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
@@ -211,7 +208,6 @@ struct StringObject;
struct ArrayObject;
struct DateObject;
struct FunctionObject;
-struct BuiltinFunction;
struct ErrorObject;
struct ArgumentsObject;
struct Managed;
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 3214a716e8..f419ab53fe 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -375,12 +375,12 @@ ReturnedValue EvalFunction::evalCall(const Value *, const Value *argv, int argc,
if (function->isStrict() || isStrict) {
ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function));
ScopedValue thisObject(scope, directCall ? scope.engine->currentStackFrame->thisObject() : scope.engine->globalObject->asReturnedValue());
- return e->call(thisObject, 0, 0);
+ return e->call(thisObject, nullptr, 0);
}
ScopedValue thisObject(scope, scope.engine->currentStackFrame->thisObject());
- return function->call(thisObject, 0, 0, ctx);
+ return function->call(thisObject, nullptr, 0, ctx);
}
@@ -507,7 +507,7 @@ ReturnedValue GlobalFunctions::method_parseFloat(const FunctionObject *b, const
QByteArray ba = trimmed.toLatin1();
bool ok;
const char *begin = ba.constData();
- const char *end = 0;
+ const char *end = nullptr;
double d = qstrtod(begin, &end, &ok);
if (end - begin == 0)
RETURN_RESULT(Encode(std::numeric_limits<double>::quiet_NaN())); // 3
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index e35f72b820..c122bcb51a 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -75,13 +75,13 @@ IdentifierHashData::IdentifierHashData(IdentifierHashData *other)
memcpy(entries, other->entries, alloc*sizeof(IdentifierHashEntry));
}
-IdentifierHashBase::IdentifierHashBase(ExecutionEngine *engine)
+IdentifierHash::IdentifierHash(ExecutionEngine *engine)
{
d = new IdentifierHashData(3);
d->identifierTable = engine->identifierTable;
}
-void IdentifierHashBase::detach()
+void IdentifierHash::detach()
{
if (!d || d->refCount == 1)
return;
@@ -92,7 +92,7 @@ void IdentifierHashBase::detach()
}
-IdentifierHashEntry *IdentifierHashBase::addEntry(const Identifier *identifier)
+IdentifierHashEntry *IdentifierHash::addEntry(const Identifier *identifier)
{
// fill up to max 50%
bool grow = (d->alloc <= d->size*2);
@@ -129,16 +129,16 @@ IdentifierHashEntry *IdentifierHashBase::addEntry(const Identifier *identifier)
return d->entries + idx;
}
-const IdentifierHashEntry *IdentifierHashBase::lookup(const Identifier *identifier) const
+const IdentifierHashEntry *IdentifierHash::lookup(const Identifier *identifier) const
{
if (!d)
- return 0;
+ return nullptr;
Q_ASSERT(d->entries);
uint idx = identifier->hashValue % d->alloc;
while (1) {
if (!d->entries[idx].identifier)
- return 0;
+ return nullptr;
if (d->entries[idx].identifier == identifier)
return d->entries + idx;
++idx;
@@ -146,17 +146,17 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const Identifier *identifi
}
}
-const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
+const IdentifierHashEntry *IdentifierHash::lookup(const QString &str) const
{
if (!d)
- return 0;
+ return nullptr;
Q_ASSERT(d->entries);
uint hash = String::createHashValue(str.constData(), str.length(), nullptr);
uint idx = hash % d->alloc;
while (1) {
if (!d->entries[idx].identifier)
- return 0;
+ return nullptr;
if (d->entries[idx].identifier->string == str)
return d->entries + idx;
++idx;
@@ -164,22 +164,22 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
}
}
-const IdentifierHashEntry *IdentifierHashBase::lookup(String *str) const
+const IdentifierHashEntry *IdentifierHash::lookup(String *str) const
{
if (!d)
- return 0;
+ return nullptr;
if (str->d()->identifier)
return lookup(str->d()->identifier);
return lookup(str->toQString());
}
-const Identifier *IdentifierHashBase::toIdentifier(const QString &str) const
+const Identifier *IdentifierHash::toIdentifier(const QString &str) const
{
Q_ASSERT(d);
return d->identifierTable->identifier(str);
}
-const Identifier *IdentifierHashBase::toIdentifier(Heap::String *str) const
+const Identifier *IdentifierHash::toIdentifier(Heap::String *str) const
{
Q_ASSERT(d);
return d->identifierTable->identifier(str);
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index 2695bbc875..82346d5f68 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -73,13 +73,7 @@ struct Identifier
struct IdentifierHashEntry {
const Identifier *identifier;
- union {
- int value;
- void *pointer;
- };
- static int get(const IdentifierHashEntry *This, int *) { return This ? This->value : -1; }
- static bool get(const IdentifierHashEntry *This, bool *) { return This != 0; }
- static void *get(const IdentifierHashEntry *This, void **) { return This ? This->pointer : 0; }
+ int value;
};
struct IdentifierHashData
@@ -98,26 +92,30 @@ struct IdentifierHashData
IdentifierHashEntry *entries;
};
-struct IdentifierHashBase
+struct IdentifierHash
{
- IdentifierHashData *d;
+ IdentifierHashData *d = nullptr;
- IdentifierHashBase() : d(0) {}
- IdentifierHashBase(ExecutionEngine *engine);
- inline IdentifierHashBase(const IdentifierHashBase &other);
- inline ~IdentifierHashBase();
- inline IdentifierHashBase &operator=(const IdentifierHashBase &other);
+ IdentifierHash() {}
+ IdentifierHash(ExecutionEngine *engine);
+ inline IdentifierHash(const IdentifierHash &other);
+ inline ~IdentifierHash();
+ inline IdentifierHash &operator=(const IdentifierHash &other);
bool isEmpty() const { return !d; }
inline int count() const;
- bool contains(const Identifier *i) const;
- bool contains(const QString &str) const;
- bool contains(String *str) const;
void detach();
+ void add(const QString &str, int value);
+ void add(Heap::String *str, int value);
+
+ inline int value(const QString &str) const;
+ inline int value(String *str) const;
+ QString findId(int value) const;
+
protected:
IdentifierHashEntry *addEntry(const Identifier *i);
const IdentifierHashEntry *lookup(const Identifier *identifier) const;
@@ -128,43 +126,20 @@ protected:
};
-template<typename T>
-struct IdentifierHash : public IdentifierHashBase
-{
- IdentifierHash()
- : IdentifierHashBase() {}
- IdentifierHash(ExecutionEngine *engine)
- : IdentifierHashBase(engine) {}
- inline IdentifierHash(const IdentifierHash<T> &other)
- : IdentifierHashBase(other) {}
- inline ~IdentifierHash() {}
- inline IdentifierHash &operator=(const IdentifierHash<T> &other) {
- IdentifierHashBase::operator =(other);
- return *this;
- }
-
- void add(const QString &str, const T &value);
- void add(Heap::String *str, const T &value);
-
- inline T value(const QString &str) const;
- inline T value(String *str) const;
- QString findId(T value) const;
-};
-
-inline IdentifierHashBase::IdentifierHashBase(const IdentifierHashBase &other)
+inline IdentifierHash::IdentifierHash(const IdentifierHash &other)
{
d = other.d;
if (d)
d->refCount.ref();
}
-inline IdentifierHashBase::~IdentifierHashBase()
+inline IdentifierHash::~IdentifierHash()
{
if (d && !d->refCount.deref())
delete d;
}
-IdentifierHashBase &IdentifierHashBase::operator=(const IdentifierHashBase &other)
+IdentifierHash &IdentifierHash::operator=(const IdentifierHash &other)
{
if (other.d)
other.d->refCount.ref();
@@ -174,60 +149,45 @@ IdentifierHashBase &IdentifierHashBase::operator=(const IdentifierHashBase &othe
return *this;
}
-inline int IdentifierHashBase::count() const
+inline int IdentifierHash::count() const
{
return d ? d->size : 0;
}
-inline bool IdentifierHashBase::contains(const Identifier *i) const
-{
- return lookup(i) != 0;
-}
-
-inline bool IdentifierHashBase::contains(const QString &str) const
-{
- return lookup(str) != 0;
-}
-
-inline bool IdentifierHashBase::contains(String *str) const
-{
- return lookup(str) != 0;
-}
-
-template<typename T>
-void IdentifierHash<T>::add(const QString &str, const T &value)
+inline
+void IdentifierHash::add(const QString &str, int value)
{
IdentifierHashEntry *e = addEntry(toIdentifier(str));
e->value = value;
}
-template<typename T>
-void IdentifierHash<T>::add(Heap::String *str, const T &value)
+inline
+void IdentifierHash::add(Heap::String *str, int value)
{
IdentifierHashEntry *e = addEntry(toIdentifier(str));
e->value = value;
}
-template<typename T>
-inline T IdentifierHash<T>::value(const QString &str) const
+inline int IdentifierHash::value(const QString &str) const
{
- return IdentifierHashEntry::get(lookup(str), (T*)0);
+ const IdentifierHashEntry *e = lookup(str);
+ return e ? e->value : -1;
}
-template<typename T>
-inline T IdentifierHash<T>::value(String *str) const
+inline int IdentifierHash::value(String *str) const
{
- return IdentifierHashEntry::get(lookup(str), (T*)0);
+ const IdentifierHashEntry *e = lookup(str);
+ return e ? e->value : -1;
}
-template<typename T>
-QString IdentifierHash<T>::findId(T value) const
+inline
+QString IdentifierHash::findId(int value) const
{
IdentifierHashEntry *e = d->entries;
IdentifierHashEntry *end = e + d->alloc;
while (e < end) {
- if (e->identifier && IdentifierHashEntry::get(e, (T*)0) == value)
+ if (e->identifier && e->value == value)
return e->identifier->string;
++e;
}
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 3def6defbf..b77f9478d3 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -142,7 +142,7 @@ Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
return str->identifier;
uint hash = str->hashValue();
if (str->subtype == Heap::String::StringType_ArrayIndex)
- return 0;
+ return nullptr;
uint idx = hash % alloc;
while (Heap::String *e = entries[idx]) {
@@ -161,7 +161,7 @@ Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
Heap::String *IdentifierTable::stringFromIdentifier(Identifier *i)
{
if (!i)
- return 0;
+ return nullptr;
uint idx = i->hashValue % alloc;
while (1) {
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 3e04ed63df..aaf5e3b857 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -61,7 +61,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine,
QV4::QmlContext *qmlContext, const QV4::Value &callback)
: v4(engine), m_url(url)
#if QT_CONFIG(qml_network)
- , m_redirectCount(0), m_network(0) , m_reply(0)
+ , m_redirectCount(0), m_network(nullptr) , m_reply(nullptr)
#endif
{
if (qmlContext)
@@ -88,7 +88,7 @@ QV4Include::~QV4Include()
{
#if QT_CONFIG(qml_network)
delete m_reply;
- m_reply = 0;
+ m_reply = nullptr;
#endif
}
@@ -196,10 +196,10 @@ void QV4Include::finished()
/*
Documented in qv8engine.cpp
*/
-QV4::ReturnedValue QV4Include::method_include(const QV4::BuiltinFunction *b, QV4::CallData *callData)
+QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
{
QV4::Scope scope(b);
- if (!callData->argc())
+ if (!argc)
RETURN_UNDEFINED();
QQmlContextData *context = scope.engine->callingQmlContext();
@@ -208,11 +208,11 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::BuiltinFunction *b, QV4
RETURN_RESULT(scope.engine->throwError(QString::fromUtf8("Qt.include(): Can only be called from JavaScript files")));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (callData->argc() >= 2 && callData->args[1].as<QV4::FunctionObject>())
- callbackFunction = callData->args[1];
+ if (argc >= 2 && argv[1].as<QV4::FunctionObject>())
+ callbackFunction = argv[1];
#if QT_CONFIG(qml_network)
- QUrl url(scope.engine->resolvedUrl(callData->args[0].toQStringNoThrow()));
+ QUrl url(scope.engine->resolvedUrl(argv[0].toQStringNoThrow()));
if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
@@ -227,21 +227,7 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::BuiltinFunction *b, QV4
} else {
QScopedPointer<QV4::Script> script;
-
- if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
- QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
- script.reset(new QV4::Script(scope.engine, qmlcontext, jsUnit));
- } else {
- QFile f(localFile);
-
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray data = f.readAll();
- QString code = QString::fromUtf8(data);
- QmlIR::Document::removeScriptPragmas(code);
-
- script.reset(new QV4::Script(scope.engine, qmlcontext, code, url.toString()));
- }
- }
+ script.reset(QV4::Script::createFromFileOrCache(scope.engine, qmlcontext, localFile, url));
if (!script.isNull()) {
script->parse();
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 68537ba2e8..8015722afc 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -77,7 +77,7 @@ public:
Exception = 3
};
- static QV4::ReturnedValue method_include(const QV4::BuiltinFunction *, QV4::CallData *callData);
+ static QV4::ReturnedValue method_include(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
private Q_SLOTS:
void finished();
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index d439884ca2..9da854e7d7 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -105,10 +105,10 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
InternalClass::InternalClass(ExecutionEngine *engine)
: engine(engine)
- , vtable(0)
- , prototype(0)
- , m_sealed(0)
- , m_frozen(0)
+ , vtable(nullptr)
+ , prototype(nullptr)
+ , m_sealed(nullptr)
+ , m_frozen(nullptr)
, size(0)
, extensible(true)
{
@@ -124,8 +124,8 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
, propertyTable(other.propertyTable)
, nameMap(other.nameMap)
, propertyData(other.propertyData)
- , m_sealed(0)
- , m_frozen(0)
+ , m_sealed(nullptr)
+ , m_frozen(nullptr)
, size(other.size)
, extensible(other.extensible)
, isUsedAsProto(other.isUsedAsProto)
@@ -149,6 +149,9 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals
int size = o->internalClass->size;
for (int i = idx; i < size; ++i)
o->setProperty(v4, i, *o->propertyData(i + (accessor ? 2 : 1)));
+ o->setProperty(v4, size, Primitive::undefinedValue());
+ if (accessor)
+ o->setProperty(v4, size + 1, Primitive::undefinedValue());
}
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
@@ -220,7 +223,7 @@ InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
Q_ASSERT(prototype != proto);
Q_ASSERT(!proto || proto->internalClass->isUsedAsProto);
- Transition temp = { { nullptr }, 0, Transition::PrototypeChange };
+ Transition temp = { { nullptr }, nullptr, Transition::PrototypeChange };
temp.prototype = proto;
Transition &t = lookupOrInsertTransition(temp);
@@ -484,7 +487,7 @@ void InternalClass::destroy()
destroyStack.pop_back();
if (!next->engine)
continue;
- next->engine = 0;
+ next->engine = nullptr;
next->propertyTable.~PropertyHash();
next->nameMap.~SharedInternalClassData<Identifier *>();
next->propertyData.~SharedInternalClassData<PropertyAttributes>();
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 546073dcf5..b689272006 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -277,10 +277,10 @@ struct InternalClass : public QQmlJS::Managed {
}
static void addMember(Object *object, String *string, PropertyAttributes data, uint *index);
- Q_REQUIRED_RESULT InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0);
- Q_REQUIRED_RESULT InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = 0);
- Q_REQUIRED_RESULT InternalClass *changeMember(Identifier *identifier, PropertyAttributes data, uint *index = 0);
- static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = 0);
+ Q_REQUIRED_RESULT InternalClass *addMember(String *string, PropertyAttributes data, uint *index = nullptr);
+ Q_REQUIRED_RESULT InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = nullptr);
+ Q_REQUIRED_RESULT InternalClass *changeMember(Identifier *identifier, PropertyAttributes data, uint *index = nullptr);
+ static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = nullptr);
static void removeMember(Object *object, Identifier *id);
uint find(const String *string);
uint find(const Identifier *id)
diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h
index 6d641bf9c5..c676b57c51 100644
--- a/src/qml/jsruntime/qv4jscall_p.h
+++ b/src/qml/jsruntime/qv4jscall_p.h
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct JSCallData {
- JSCallData(const Scope &scope, int argc = 0, const Value *argv = 0, const Value *thisObject = 0)
+ JSCallData(const Scope &scope, int argc = 0, const Value *argv = nullptr, const Value *thisObject = nullptr)
: scope(scope), argc(argc)
{
if (thisObject)
@@ -124,7 +124,7 @@ struct ScopedStackFrame {
return;
frame.jsFrame = reinterpret_cast<CallData *>(scope.alloc(sizeof(CallData)/sizeof(Value)));
frame.jsFrame->context = context;
- frame.v4Function = frame.parent ? frame.parent->v4Function : 0;
+ frame.v4Function = frame.parent ? frame.parent->v4Function : nullptr;
scope.engine->currentStackFrame = &frame;
}
~ScopedStackFrame() {
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 5e580b8b4d..99666806be 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -634,7 +634,7 @@ struct Stringify
return false;
}
- Stringify(ExecutionEngine *e) : v4(e), replacerFunction(0), propertyList(0), propertyListSize(0) {}
+ Stringify(ExecutionEngine *e) : v4(e), replacerFunction(nullptr), propertyList(nullptr), propertyListSize(0) {}
QString Str(const QString &key, const Value &v);
QString JA(ArrayObject *a);
@@ -884,12 +884,12 @@ void Heap::JsonObject::init()
}
-ReturnedValue JsonObject::method_parse(const BuiltinFunction *b, CallData *callData)
+ReturnedValue JsonObject::method_parse(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
ExecutionEngine *v4 = b->engine();
QString jtext;
- if (callData->argc() > 0)
- jtext = callData->args[0].toQString();
+ if (argc > 0)
+ jtext = argv[0].toQString();
DEBUG << "parsing source = " << jtext;
JsonParser parser(v4, jtext.constData(), jtext.length());
@@ -903,12 +903,12 @@ ReturnedValue JsonObject::method_parse(const BuiltinFunction *b, CallData *callD
return result;
}
-ReturnedValue JsonObject::method_stringify(const BuiltinFunction *b, CallData *callData)
+ReturnedValue JsonObject::method_stringify(const FunctionObject *b, const Value *, const Value *argv, int argc)
{
Scope scope(b);
Stringify stringify(scope.engine);
- ScopedObject o(scope, callData->argument(1));
+ ScopedObject o(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
if (o) {
stringify.replacerFunction = o->as<FunctionObject>();
if (o->isArrayObject()) {
@@ -920,11 +920,11 @@ ReturnedValue JsonObject::method_stringify(const BuiltinFunction *b, CallData *c
if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber())
*v = v->toString(scope.engine);
if (!v->isString()) {
- v->setM(0);
+ v->setM(nullptr);
} else {
for (uint j = 0; j <i; ++j) {
if (stringify.propertyList[j].m() == v->m()) {
- v->setM(0);
+ v->setM(nullptr);
break;
}
}
@@ -933,7 +933,7 @@ ReturnedValue JsonObject::method_stringify(const BuiltinFunction *b, CallData *c
}
}
- ScopedValue s(scope, callData->argument(2));
+ ScopedValue s(scope, argc > 2 ? argv[2] : Primitive::undefinedValue());
if (NumberObject *n = s->as<NumberObject>())
s = Encode(n->value());
else if (StringObject *so = s->as<StringObject>())
@@ -946,7 +946,7 @@ ReturnedValue JsonObject::method_stringify(const BuiltinFunction *b, CallData *c
}
- ScopedValue arg0(scope, callData->argument(0));
+ ScopedValue arg0(scope, argc ? argv[0] : Primitive::undefinedValue());
QString result = stringify.Str(QString(), arg0);
if (result.isEmpty() || scope.engine->hasException)
RETURN_UNDEFINED();
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 19dba14aef..7d9f204910 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -88,8 +88,8 @@ private:
typedef QSet<ObjectItem> V4ObjectSet;
public:
- static ReturnedValue method_parse(const BuiltinFunction *, CallData *callData);
- static ReturnedValue method_stringify(const BuiltinFunction *, CallData *callData);
+ static ReturnedValue method_parse(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_stringify(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue fromJsonValue(ExecutionEngine *engine, const QJsonValue &value);
static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object);
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 200380eda0..b50e5f0355 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -46,7 +46,7 @@ using namespace QV4;
const VTable Managed::static_vtbl =
{
- 0,
+ nullptr,
0,
0,
Managed::IsExecutionContext,
@@ -58,15 +58,15 @@ const VTable Managed::static_vtbl =
0,
Managed::MyType,
"Managed",
- 0,
- 0 /*markObjects*/,
+ nullptr,
+ nullptr /*markObjects*/,
isEqualTo
};
QString Managed::className() const
{
- const char *s = 0;
+ const char *s = nullptr;
switch (Type(d()->vtable()->type)) {
case Type_Invalid:
case Type_String:
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index f81dcf9479..092c61b81c 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -93,7 +93,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
dptr->_checkIsInitialized(); \
return dptr; \
} \
- V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass)
+ Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
#define V4_MANAGED(DataClass, superClass) \
private: \
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 252ec345d9..0c18d908de 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -277,7 +277,7 @@ ReturnedValue MathObject::method_pow(const FunctionObject *, const Value *, cons
ReturnedValue MathObject::method_random(const FunctionObject *, const Value *, const Value *, int)
{
- RETURN_RESULT(Encode(QRandomGenerator::getReal()));
+ RETURN_RESULT(Encode(QRandomGenerator::global()->generateDouble()));
}
ReturnedValue MathObject::method_round(const FunctionObject *, const Value *, const Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 3e231d693b..ac9671254d 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -65,7 +65,7 @@ namespace Heap {
DECLARE_HEAP_OBJECT(MemberData, Base) {
DECLARE_MARKOBJECTS(MemberData);
};
-V4_ASSERT_IS_TRIVIAL(MemberData)
+Q_STATIC_ASSERT(std::is_trivial< MemberData >::value);
}
@@ -79,7 +79,7 @@ struct MemberData : Managed
Value *slot;
void set(EngineBase *e, Value newVal) {
- WriteBarrier::write(e, base, slot, newVal);
+ WriteBarrier::write(e, base, slot->data_ptr(), newVal.asReturnedValue());
}
const Value *operator->() const { return slot; }
const Value &operator*() const { return *slot; }
@@ -93,7 +93,7 @@ struct MemberData : Managed
inline uint size() const { return d()->values.size; }
- static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old = 0);
+ static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old = nullptr);
};
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index b4034fd196..8e9bf794a9 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -94,7 +94,7 @@ void Heap::Object::setUsedAsProto()
bool Object::setPrototype(Object *proto)
{
- Heap::Object *p = proto ? proto->d() : 0;
+ Heap::Object *p = proto ? proto->d() : nullptr;
Heap::Object *pp = p;
while (pp) {
if (pp == d())
@@ -156,34 +156,13 @@ void Object::defineDefaultProperty(const QString &name, const Value &value)
defineDefaultProperty(s, value);
}
-void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount)
-{
- ExecutionEngine *e = engine();
- Scope scope(e);
- ScopedString s(scope, e->newIdentifier(name));
- ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
- function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
- defineDefaultProperty(s, function);
-}
-
-void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount)
-{
- ExecutionEngine *e = engine();
- Scope scope(e);
- ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
- function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
- defineDefaultProperty(name, function);
-}
-
void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
{
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
+ ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, s, code));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
@@ -193,32 +172,11 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const Fun
ExecutionEngine *e = engine();
Scope scope(e);
ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
+ ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, name, code));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
-void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *),
- ReturnedValue (*setter)(const BuiltinFunction *, CallData *))
-{
- ExecutionEngine *e = engine();
- Scope scope(e);
- ScopedString s(scope, e->newIdentifier(name));
- defineAccessorProperty(s, getter, setter);
-}
-
-void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *),
- ReturnedValue (*setter)(const BuiltinFunction *, CallData *))
-{
- ExecutionEngine *v4 = engine();
- QV4::Scope scope(v4);
- ScopedProperty p(scope);
- 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);
-}
-
void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int))
{
@@ -235,8 +193,8 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(const
QV4::Scope scope(v4);
ScopedProperty p(scope);
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)));
+ p->setGetter(ScopedFunctionObject(scope, (getter ? FunctionObject::createBuiltinFunction(global, name, getter) : nullptr)));
+ p->setSetter(ScopedFunctionObject(scope, (setter ? FunctionObject::createBuiltinFunction(global, name, setter) : nullptr)));
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
@@ -268,11 +226,6 @@ void Object::defineReadonlyConfigurableProperty(String *name, const Value &value
insertMember(name, value, Attr_ReadOnly_ButConfigurable);
}
-void Object::markObjects(Heap::Base *base, MarkStack *stack)
-{
- Heap::Object::markObjects(base, stack);
-}
-
void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
{
Object *o = static_cast<Object *>(b);
@@ -368,7 +321,7 @@ MemberData::Index Object::getValueOrSetter(String *name, PropertyAttributes *att
o = o->prototype();
}
*attrs = Attr_Invalid;
- return { 0, 0 };
+ return { nullptr, nullptr };
}
ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
@@ -393,7 +346,7 @@ ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
o = o->prototype();
}
*attrs = Attr_Invalid;
- return { 0, 0 };
+ return { nullptr, 0 };
}
bool Object::hasProperty(String *name) const
@@ -531,7 +484,7 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
- name->setM(0);
+ name->setM(nullptr);
*index = UINT_MAX;
if (o->arrayData()) {
@@ -555,7 +508,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *
return;
}
}
- it->arrayNode = 0;
+ it->arrayNode = nullptr;
it->arrayIndex = UINT_MAX;
}
// dense arrays
@@ -675,7 +628,7 @@ bool Object::internalPut(String *name, const Value &value)
name->makeIdentifier();
Identifier *id = name->identifier();
- MemberData::Index memberIndex{0, 0};
+ MemberData::Index memberIndex{nullptr, nullptr};
uint member = internalClass()->find(id);
PropertyAttributes attrs;
if (member < UINT_MAX) {
@@ -751,7 +704,7 @@ bool Object::internalPutIndexed(uint index, const Value &value)
PropertyAttributes attrs;
- ArrayData::Index arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : ArrayData::Index{ 0, 0 };
+ ArrayData::Index arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : ArrayData::Index{ nullptr, 0 };
if (arrayIndex.isNull() && isStringObject()) {
if (index < static_cast<StringObject *>(this)->length())
@@ -945,7 +898,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
return true;
}
- return __defineOwnProperty__(engine, index, 0, p, attrs);
+ return __defineOwnProperty__(engine, index, nullptr, p, attrs);
}
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs)
@@ -996,8 +949,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
Q_ASSERT(arrayData());
setArrayAttributes(index, cattrs);
}
- current->setGetter(0);
- current->setSetter(0);
+ current->setGetter(nullptr);
+ current->setSetter(nullptr);
} else {
// 9c
cattrs.setType(PropertyAttributes::Data);
@@ -1069,7 +1022,6 @@ void Object::copyArrayData(Object *other)
Heap::ArrayData *od = other->d()->arrayData;
Heap::ArrayData *dd = d()->arrayData;
dd->sparse = new SparseArray(*od->sparse);
- dd->freeList = od->freeList;
} else {
Heap::ArrayData *dd = d()->arrayData;
dd->values.size = other->d()->arrayData->values.size;
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 66177617f7..1731ae3c76 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -64,8 +64,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct BuiltinFunction;
-
namespace Heap {
#define ObjectMembers(class, Member) \
@@ -87,12 +85,12 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
void setInlineProperty(ExecutionEngine *e, uint index, Value v) {
Q_ASSERT(index < vtable()->nInlineProperties);
Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
- WriteBarrier::write(e, this, prop, v);
+ WriteBarrier::write(e, this, prop->data_ptr(), v.asReturnedValue());
}
void setInlineProperty(ExecutionEngine *e, uint index, Heap::Base *b) {
Q_ASSERT(index < vtable()->nInlineProperties);
Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index;
- WriteBarrier::write(e, this, prop, b);
+ WriteBarrier::write(e, this, prop->data_ptr(), b->asReturnedValue());
}
QV4::MemberData::Index writablePropertyData(uint index) {
@@ -153,7 +151,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
dptr->_checkIsInitialized(); \
return dptr; \
} \
- V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass);
+ Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
#define V4_PROTOTYPE(p) \
static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
@@ -238,8 +236,8 @@ struct Q_QML_EXPORT Object: Managed {
Heap::Object *prototype() const { return d()->prototype(); }
bool setPrototype(Object *proto);
- void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = 0);
- void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = 0);
+ void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = nullptr);
+ void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = nullptr);
MemberData::Index getValueOrSetter(String *name, PropertyAttributes *attrs);
ArrayData::Index getValueOrSetter(uint index, PropertyAttributes *attrs);
@@ -273,16 +271,8 @@ struct Q_QML_EXPORT Object: Managed {
insertMember(name, value, Attr_Data|Attr_NotEnumerable);
}
void defineDefaultProperty(const QString &name, const Value &value);
- // old calling convention
- void defineDefaultProperty(const QString &name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount = 0);
- void defineDefaultProperty(String *name, ReturnedValue (*code)(const BuiltinFunction *, CallData *), int argumentCount = 0);
- // new calling convention
void defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount = 0);
void defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount = 0);
- void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *),
- ReturnedValue (*setter)(const BuiltinFunction *, CallData *));
- void defineAccessorProperty(String *name, ReturnedValue (*getter)(const BuiltinFunction *, CallData *),
- ReturnedValue (*setter)(const BuiltinFunction *, CallData *));
void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int));
void defineAccessorProperty(String *name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
@@ -308,8 +298,6 @@ struct Q_QML_EXPORT Object: Managed {
// Array handling
public:
- static void markObjects(Heap::Base *base, MarkStack *stack);
-
void copyArrayData(Object *other);
bool setArrayLength(uint newLen);
@@ -358,8 +346,8 @@ public:
}
void initSparseArray();
- SparseArrayNode *sparseBegin() { return arrayType() == Heap::ArrayData::Sparse ? d()->arrayData->sparse->begin() : 0; }
- SparseArrayNode *sparseEnd() { return arrayType() == Heap::ArrayData::Sparse ? d()->arrayData->sparse->end() : 0; }
+ SparseArrayNode *sparseBegin() { return arrayType() == Heap::ArrayData::Sparse ? d()->arrayData->sparse->begin() : nullptr; }
+ SparseArrayNode *sparseEnd() { return arrayType() == Heap::ArrayData::Sparse ? d()->arrayData->sparse->end() : nullptr; }
inline bool protoHasArray() {
Scope scope(engine());
@@ -372,9 +360,9 @@ public:
return false;
}
- inline ReturnedValue get(String *name, bool *hasProperty = 0) const
+ inline ReturnedValue get(String *name, bool *hasProperty = nullptr) const
{ return vtable()->get(this, name, hasProperty); }
- inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const
+ inline ReturnedValue getIndexed(uint idx, bool *hasProperty = nullptr) const
{ return vtable()->getIndexed(this, idx, hasProperty); }
// use the set variants instead, to customize throw behavior
@@ -563,7 +551,7 @@ inline void Object::arraySet(uint index, const Value &value)
template<>
inline const ArrayObject *Value::as() const {
- return isManaged() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : 0;
+ return isManaged() && m()->vtable()->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : nullptr;
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 0394c704f9..7bf7e1aa04 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -47,8 +47,8 @@ using namespace QV4;
void ObjectIterator::init(const Object *o)
{
- object->setM(o ? o->m() : 0);
- current->setM(o ? o->m() : 0);
+ object->setM(o ? o->m() : nullptr);
+ current->setM(o ? o->m() : nullptr);
if (object->as<ArgumentsObject>()) {
Scope scope(engine);
@@ -58,7 +58,7 @@ void ObjectIterator::init(const Object *o)
void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
- name->setM(0);
+ name->setM(nullptr);
*index = UINT_MAX;
if (!object->as<Object>()) {
@@ -100,7 +100,7 @@ void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttrib
if (flags & WithProtoChain)
current->setM(co->prototype());
else
- current->setM(0);
+ current->setM(nullptr);
arrayIndex = 0;
memberIndex = 0;
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 30a6ad3025..744d16301a 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -73,7 +73,7 @@ struct Q_QML_EXPORT ObjectIteratorData
uint memberIndex;
uint flags;
};
-V4_ASSERT_IS_TRIVIAL(ObjectIteratorData)
+Q_STATIC_ASSERT(std::is_trivial< ObjectIteratorData >::value);
struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData
{
@@ -101,7 +101,7 @@ struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData
init(o);
}
- void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = nullptr);
ReturnedValue nextPropertyName(Value *value);
ReturnedValue nextPropertyNameAsString(Value *value);
ReturnedValue nextPropertyNameAsString();
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 5eef757ce9..b998b78520 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -121,8 +121,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
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);
+ p->value = FunctionObject::createBuiltinFunction(global, v4->id___proto__(), method_get_proto);
+ p->set = FunctionObject::createBuiltinFunction(global, v4->id___proto__(), method_set_proto);
insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable);
}
@@ -638,7 +638,7 @@ ReturnedValue ObjectPrototype::method_set_proto(const FunctionObject *b, const V
THROW_TYPE_ERROR();
if (argv[0].isNull()) {
- o->setPrototype(0);
+ o->setPrototype(nullptr);
RETURN_UNDEFINED();
}
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 0b31c971f9..7fc74173e3 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -68,6 +68,22 @@ Page *getPage(Value *val) {
return reinterpret_cast<Page *>(reinterpret_cast<quintptr>(val) & ~((quintptr)(WTF::pageSize() - 1)));
}
+QML_NEARLY_ALWAYS_INLINE void insertInFront(PersistentValueStorage *storage, Page *p)
+{
+ p->header.next = reinterpret_cast<Page *>(storage->firstPage);
+ p->header.prev = reinterpret_cast<Page **>(&storage->firstPage);
+ if (p->header.next)
+ p->header.next->header.prev = &p->header.next;
+ storage->firstPage = p;
+}
+
+QML_NEARLY_ALWAYS_INLINE void unlink(Page *p)
+{
+ if (p->header.prev)
+ *p->header.prev = p->header.next;
+ if (p->header.next)
+ p->header.next->header.prev = p->header.prev;
+}
Page *allocatePage(PersistentValueStorage *storage)
{
@@ -78,19 +94,14 @@ Page *allocatePage(PersistentValueStorage *storage)
p->header.engine = storage->engine;
p->header.alloc = page;
- p->header.next = reinterpret_cast<Page *>(storage->firstPage);
- p->header.prev = reinterpret_cast<Page **>(&storage->firstPage);
p->header.refCount = 0;
p->header.freeList = 0;
- if (p->header.next)
- p->header.next->header.prev = &p->header.next;
+ insertInFront(storage, p);
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
p->values[i].setEmpty(i + 1);
}
p->values[kEntriesPerPage - 1].setEmpty(-1);
- storage->firstPage = p;
-
return p;
}
@@ -161,7 +172,7 @@ Value &PersistentValueStorage::Iterator::operator *()
PersistentValueStorage::PersistentValueStorage(ExecutionEngine *engine)
: engine(engine),
- firstPage(0)
+ firstPage(nullptr)
{
}
@@ -174,9 +185,9 @@ PersistentValueStorage::~PersistentValueStorage()
p->values[i] = Encode::undefined();
}
Page *n = p->header.next;
- p->header.engine = 0;
- p->header.prev = 0;
- p->header.next = 0;
+ p->header.engine = nullptr;
+ p->header.prev = nullptr;
+ p->header.next = nullptr;
Q_ASSERT(p->header.refCount);
p = n;
}
@@ -195,6 +206,12 @@ Value *PersistentValueStorage::allocate()
Value *v = p->values + p->header.freeList;
p->header.freeList = v->int_32();
+
+ if (p->header.freeList != -1 && p != firstPage) {
+ unlink(p);
+ insertInFront(this, p);
+ }
+
++p->header.refCount;
v->setRawValue(Encode::undefined());
@@ -237,16 +254,13 @@ ExecutionEngine *PersistentValueStorage::getEngine(Value *v)
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;
+ unlink(p);
p->header.alloc.deallocate();
}
PersistentValue::PersistentValue(const PersistentValue &other)
- : val(0)
+ : val(nullptr)
{
if (other.val) {
val = other.engine()->memoryManager->m_persistentValues->allocate();
@@ -267,7 +281,7 @@ PersistentValue::PersistentValue(ExecutionEngine *engine, ReturnedValue value)
}
PersistentValue::PersistentValue(ExecutionEngine *engine, Object *object)
- : val(0)
+ : val(nullptr)
{
if (!object)
return;
@@ -344,7 +358,7 @@ void PersistentValue::set(ExecutionEngine *engine, Heap::Base *obj)
}
WeakValue::WeakValue(const WeakValue &other)
- : val(0)
+ : val(nullptr)
{
if (other.val) {
allocVal(other.engine());
@@ -404,6 +418,6 @@ void WeakValue::free()
PersistentValueStorage::free(val);
}
- val = 0;
+ val = nullptr;
}
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 1f838f5531..55e8eefcb7 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -81,7 +81,7 @@ struct Q_QML_EXPORT PersistentValueStorage
Value &operator *();
};
Iterator begin() { return Iterator(firstPage, 0); }
- Iterator end() { return Iterator(0, 0); }
+ Iterator end() { return Iterator(nullptr, 0); }
static ExecutionEngine *getEngine(Value *v);
@@ -94,7 +94,7 @@ private:
class Q_QML_EXPORT PersistentValue
{
public:
- PersistentValue() : val(0) {}
+ PersistentValue() {}
PersistentValue(const PersistentValue &other);
PersistentValue &operator=(const PersistentValue &other);
PersistentValue &operator=(const WeakValue &other);
@@ -117,19 +117,19 @@ public:
}
Managed *asManaged() const {
if (!val)
- return 0;
+ return nullptr;
return val->managed();
}
template<typename T>
T *as() const {
if (!val)
- return 0;
+ return nullptr;
return val->as<T>();
}
ExecutionEngine *engine() const {
if (!val)
- return 0;
+ return nullptr;
return PersistentValueStorage::getEngine(val);
}
@@ -137,18 +137,18 @@ public:
bool isNullOrUndefined() const { return !val || val->isNullOrUndefined(); }
void clear() {
PersistentValueStorage::free(val);
- val = 0;
+ val = nullptr;
}
bool isEmpty() { return !val; }
private:
- Value *val;
+ Value *val = nullptr;
};
class Q_QML_EXPORT WeakValue
{
public:
- WeakValue() : val(0) {}
+ WeakValue() {}
WeakValue(const WeakValue &other);
WeakValue(ExecutionEngine *engine, const Value &value);
WeakValue &operator=(const WeakValue &other);
@@ -183,19 +183,19 @@ public:
}
Managed *asManaged() const {
if (!val)
- return 0;
+ return nullptr;
return val->managed();
}
template <typename T>
T *as() const {
if (!val)
- return 0;
+ return nullptr;
return val->as<T>();
}
ExecutionEngine *engine() const {
if (!val)
- return 0;
+ return nullptr;
return PersistentValueStorage::getEngine(val);
}
@@ -206,7 +206,7 @@ public:
void markOnce(MarkStack *markStack);
private:
- Value *val;
+ Value *val = nullptr;
private:
Q_NEVER_INLINE void allocVal(ExecutionEngine *engine);
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index bedcb5b164..5fd200efc1 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -120,7 +120,8 @@ void Profiler::startProfiling(quint64 features)
if (features & (1 << FeatureMemoryAllocation)) {
qint64 timestamp = m_timer.nsecsElapsed();
MemoryAllocationProperties heap = {timestamp,
- (qint64)m_engine->memoryManager->getAllocatedMem(),
+ (qint64)m_engine->memoryManager->getAllocatedMem() -
+ (qint64)m_engine->memoryManager->getLargeItemsMem(),
HeapPage};
m_memory_data.append(heap);
MemoryAllocationProperties small = {timestamp,
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 8a24c71815..e8c154e4e7 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -59,12 +59,18 @@
#if !QT_CONFIG(qml_debug)
+#define Q_V4_PROFILE_ALLOC(engine, size, type) (!engine)
+#define Q_V4_PROFILE_DEALLOC(engine, size, type) (!engine)
QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Profiling {
class Profiler {};
+class FunctionCallProfiler {
+public:
+ FunctionCallProfiler(ExecutionEngine *, Function *) {}
+};
}
}
@@ -72,6 +78,16 @@ QT_END_NAMESPACE
#else
+#define Q_V4_PROFILE_ALLOC(engine, size, type)\
+ (engine->profiler() &&\
+ (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
+ engine->profiler()->trackAlloc(size, type) : false)
+
+#define Q_V4_PROFILE_DEALLOC(engine, size, type) \
+ (engine->profiler() &&\
+ (engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
+ engine->profiler()->trackDealloc(size, type) : false)
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -123,7 +139,7 @@ struct MemoryAllocationProperties {
class FunctionCall {
public:
- FunctionCall() : m_function(0), m_start(0), m_end(0)
+ FunctionCall() : m_function(nullptr), m_start(0), m_end(0)
{ Q_ASSERT_X(false, Q_FUNC_INFO, "Cannot construct a function call without function"); }
FunctionCall(Function *function, qint64 start, qint64 end) :
@@ -211,16 +227,24 @@ public:
bool trackAlloc(size_t size, MemoryType type)
{
- MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
- m_memory_data.append(allocation);
- return true;
+ if (size) {
+ MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
+ m_memory_data.append(allocation);
+ return true;
+ } else {
+ return false;
+ }
}
bool trackDealloc(size_t size, MemoryType type)
{
- MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
- m_memory_data.append(allocation);
- return true;
+ if (size) {
+ MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
+ m_memory_data.append(allocation);
+ return true;
+ } else {
+ return false;
+ }
}
quint64 featuresEnabled;
@@ -252,7 +276,7 @@ public:
// It's enough to ref() the function in the destructor as it will probably not disappear while
// it's executing ...
FunctionCallProfiler(ExecutionEngine *engine, Function *f)
- : profiler(0)
+ : profiler(nullptr)
{
Profiler *p = engine->profiler();
if (Q_UNLIKELY(p) && (p->featuresEnabled & (1 << Profiling::FeatureFunctionCall))) {
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index 2a5b6f7f74..7cb106c424 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -84,7 +84,7 @@ struct Property {
inline Heap::FunctionObject *getter() const { return reinterpret_cast<Heap::FunctionObject *>(value.heapObject()); }
inline Heap::FunctionObject *setter() const { return reinterpret_cast<Heap::FunctionObject *>(set.heapObject()); }
inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
- inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : 0); }
+ inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : nullptr); }
void copy(const Property *other, PropertyAttributes attrs) {
value = other->value;
@@ -92,7 +92,7 @@ struct Property {
set = other->set;
}
- explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
+ explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(nullptr); }
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
value.setM(reinterpret_cast<Heap::Base *>(getter));
set.setM(reinterpret_cast<Heap::Base *>(setter));
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 5a165b2309..040f060476 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -108,8 +108,8 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
return result->asReturnedValue();
}
- // Its possible we could delay the calculation of the "actual" context (in the case
- // of sub contexts) until it is definately needed.
+ // It's possible we could delay the calculation of the "actual" context (in the case
+ // of sub contexts) until it is definitely needed.
QQmlContextData *context = resource->getContext();
QQmlContextData *expressionContext = context;
@@ -138,7 +138,9 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
*hasProperty = true;
if (r.scriptIndex != -1) {
QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
- return scripts->getIndexed(r.scriptIndex);
+ if (scripts)
+ return scripts->getIndexed(r.scriptIndex);
+ return QV4::Encode::null();
} else if (r.type.isValid()) {
return QQmlTypeWrapper::create(v4, scopeObject, r.type);
} else if (r.importNamespace) {
@@ -154,7 +156,7 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
while (context) {
// Search context properties
- const QV4::IdentifierHash<int> &properties = context->propertyNames();
+ const QV4::IdentifierHash &properties = context->propertyNames();
if (properties.count()) {
int propertyIdx = properties.value(name);
@@ -200,7 +202,7 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
return result->asReturnedValue();
}
}
- scopeObject = 0;
+ scopeObject = nullptr;
// Search context object
@@ -248,8 +250,8 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
return Object::put(m, name, value);
}
- // Its possible we could delay the calculation of the "actual" context (in the case
- // of sub contexts) until it is definately needed.
+ // It's possible we could delay the calculation of the "actual" context (in the case
+ // of sub contexts) until it is definitely needed.
QQmlContextData *context = wrapper->getContext();
QQmlContextData *expressionContext = context;
@@ -261,7 +263,7 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
QObject *scopeObject = wrapper->getScopeObject();
while (context) {
- const QV4::IdentifierHash<int> &properties = context->propertyNames();
+ const QV4::IdentifierHash &properties = context->propertyNames();
// Search context properties
if (properties.count() && properties.value(name) != -1)
return false;
@@ -270,7 +272,7 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
if (scopeObject &&
QV4::QObjectWrapper::setQmlProperty(v4, context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
return true;
- scopeObject = 0;
+ scopeObject = nullptr;
// Search context object
if (context->contextObject &&
@@ -310,7 +312,7 @@ Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, cons
context->isInternal = true;
context->isJSContext = true;
- Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)0));
+ Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocObject<QQmlContextWrapper>(context, (QObject*)nullptr));
qml->d()->isNullWrapper = true;
qml->setReadOnly(false);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index a1df5cb95f..647bef7fc1 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -91,6 +91,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
{
V4_OBJECT2(QQmlContextWrapper, Object)
V4_NEEDS_DESTROY
+ V4_INTERNALCLASS(QmlContextWrapper)
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return *d()->context; }
@@ -104,6 +105,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
struct Q_QML_EXPORT QmlContext : public ExecutionContext
{
V4_MANAGED(QmlContext, ExecutionContext)
+ V4_INTERNALCLASS(QmlContext)
static Heap::QmlContext *createWorkerContext(QV4::ExecutionContext *parent, const QUrl &source, Value *sendFunction);
static Heap::QmlContext *create(QV4::ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6d7d929b61..c1bbe2a330 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -99,7 +99,7 @@ QPair<QObject *, int> QObjectMethod::extractQtMethod(const QV4::FunctionObject *
return qMakePair(method->object(), method->methodIndex());
}
- return qMakePair((QObject *)0, -1);
+ return qMakePair((QObject *)nullptr, -1);
}
static QPair<QObject *, int> extractQtSignal(const Value &value)
@@ -116,7 +116,7 @@ static QPair<QObject *, int> extractQtSignal(const Value &value)
return qMakePair(handler->object(), handler->signalIndex());
}
- return qMakePair((QObject *)0, -1);
+ return qMakePair((QObject *)nullptr, -1);
}
static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object,
@@ -126,7 +126,7 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
QV4::Scope scope(v4);
if (property.isQObject()) {
- QObject *rv = 0;
+ QObject *rv = nullptr;
property.readProperty(object, &rv);
return QV4::QObjectWrapper::wrap(v4, rv);
} else if (property.isQList()) {
@@ -194,7 +194,7 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
"'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
return QV4::Encode::undefined();
} else {
- QVariant v(property.propType(), (void *)0);
+ QVariant v(property.propType(), (void *)nullptr);
property.readProperty(object, v.data());
return scope.engine->fromVariant(v);
}
@@ -217,7 +217,7 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QObject
Q_UNUSED(revisionMode);
QQmlData *ddata = QQmlData::get(o, false);
- QQmlPropertyData *result = 0;
+ QQmlPropertyData *result = nullptr;
if (ddata && ddata->propertyCache)
result = ddata->propertyCache->property(name, o, qmlContext);
else
@@ -249,7 +249,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
}
}
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : nullptr;
if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
@@ -335,6 +335,11 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
if (!ddata)
return QV4::Encode::undefined();
+ if (Q_UNLIKELY(!ddata->propertyCache)) {
+ ddata->propertyCache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+ ddata->propertyCache->addref();
+ }
+
QQmlPropertyCache *cache = ddata->propertyCache;
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
@@ -434,7 +439,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
return;
}
- QQmlBinding *newBinding = 0;
+ QQmlBinding *newBinding = nullptr;
QV4::Scope scope(engine);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
@@ -496,9 +501,9 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex(), argv);
if (value.isNull() && property->isQObject()) {
- PROPERTY_STORE(QObject*, 0);
+ PROPERTY_STORE(QObject*, nullptr);
} else if (value.isUndefined() && property->isResettable()) {
- void *a[] = { 0 };
+ void *a[] = { nullptr };
QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex(), a);
} else if (value.isUndefined() && property->propType() == qMetaTypeId<QVariant>()) {
PROPERTY_STORE(QVariant, QVariant());
@@ -531,7 +536,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
Q_ASSERT(vmemo);
vmemo->setVMEProperty(property->coreIndex(), value);
} else if (property->propType() == qMetaTypeId<QQmlScriptString>() && (value.isUndefined() || value.isPrimitive())) {
- QQmlScriptString ss(value.toQStringNoThrow(), 0 /* context */, object);
+ QQmlScriptString ss(value.toQStringNoThrow(), nullptr /* context */, object);
if (value.isNumber()) {
ss.d->numberValue = value.toNumber();
ss.d->isNumberLiteral = true;
@@ -549,7 +554,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
- const char *valueType = 0;
+ const char *valueType = nullptr;
if (v.userType() == QVariant::Invalid) valueType = "null";
else valueType = QMetaType::typeName(v.userType());
@@ -590,7 +595,7 @@ ReturnedValue QObjectWrapper::wrap_slowPath(ExecutionEngine *engine, QObject *ob
} else {
// If this object is tainted, we have to check to see if it is in our
// tainted object list
- ScopedObject alternateWrapper(scope, (Object *)0);
+ ScopedObject alternateWrapper(scope, (Object *)nullptr);
if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object)
alternateWrapper = engine->m_multiplyWrappedQObjects->value(object);
@@ -715,6 +720,10 @@ bool QObjectWrapper::put(Managed *m, String *name, const Value &value)
PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ const QObject *thatObject = that->d()->object();
+ if (QQmlData::wasDeleted(thatObject))
+ return QV4::Object::query(m, name);
+
ExecutionEngine *engine = that->engine();
QQmlContextData *qmlContext = engine->callingQmlContext();
QQmlPropertyData local;
@@ -732,7 +741,7 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
- name->setM(0);
+ name->setM(nullptr);
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
@@ -809,7 +818,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
break;
QQmlMetaObject::ArgTypeStorage storage;
- int *argsTypes = QQmlMetaObject(r).methodParameterTypes(This->signalIndex, &storage, 0);
+ int *argsTypes = QQmlMetaObject(r).methodParameterTypes(This->signalIndex, &storage, nullptr);
int argCount = argsTypes ? argsTypes[0]:0;
@@ -838,7 +847,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QQmlEnginePrivate::get(qmlEngine)->warning(error);
} else {
QMessageLogger(error.url().toString().toLatin1().constData(),
- error.line(), 0).warning().noquote()
+ error.line(), nullptr).warning().noquote()
<< error.toString();
}
}
@@ -900,14 +909,14 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
} // namespace QV4
-ReturnedValue QObjectWrapper::method_connect(const BuiltinFunction *b, CallData *callData)
+ReturnedValue QObjectWrapper::method_connect(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
QV4::Scope scope(b);
- if (callData->argc() == 0)
+ if (argc == 0)
THROW_GENERIC_ERROR("Function.prototype.connect: no arguments given");
- QPair<QObject *, int> signalInfo = extractQtSignal(callData->thisObject);
+ QPair<QObject *, int> signalInfo = extractQtSignal(*thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second; // in method range, not signal range!
@@ -921,25 +930,25 @@ ReturnedValue QObjectWrapper::method_connect(const BuiltinFunction *b, CallData
THROW_GENERIC_ERROR("Function.prototype.connect: this object is not a signal");
QV4::ScopedFunctionObject f(scope);
- QV4::ScopedValue thisObject (scope, QV4::Encode::undefined());
+ QV4::ScopedValue object (scope, QV4::Encode::undefined());
- if (callData->argc() == 1) {
- f = callData->args[0];
- } else if (callData->argc() >= 2) {
- thisObject = callData->args[0];
- f = callData->args[1];
+ if (argc == 1) {
+ f = argv[0];
+ } else if (argc >= 2) {
+ object = argv[0];
+ f = argv[1];
}
if (!f)
THROW_GENERIC_ERROR("Function.prototype.connect: target is not a function");
- if (!thisObject->isUndefined() && !thisObject->isObject())
+ if (!object->isUndefined() && !object->isObject())
THROW_GENERIC_ERROR("Function.prototype.connect: target this is not an object");
QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher;
slot->signalIndex = signalIndex;
- slot->thisObject.set(scope.engine, thisObject);
+ slot->thisObject.set(scope.engine, object);
slot->function.set(scope.engine, f);
if (QQmlData *ddata = QQmlData::get(signalObject)) {
@@ -952,14 +961,14 @@ ReturnedValue QObjectWrapper::method_connect(const BuiltinFunction *b, CallData
RETURN_UNDEFINED();
}
-ReturnedValue QObjectWrapper::method_disconnect(const BuiltinFunction *b, CallData *callData)
+ReturnedValue QObjectWrapper::method_disconnect(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
QV4::Scope scope(b);
- if (callData->argc() == 0)
+ if (argc == 0)
THROW_GENERIC_ERROR("Function.prototype.disconnect: no arguments given");
- QPair<QObject *, int> signalInfo = extractQtSignal(callData->thisObject);
+ QPair<QObject *, int> signalInfo = extractQtSignal(*thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
@@ -975,11 +984,11 @@ ReturnedValue QObjectWrapper::method_disconnect(const BuiltinFunction *b, CallDa
QV4::ScopedFunctionObject functionValue(scope);
QV4::ScopedValue functionThisValue(scope, QV4::Encode::undefined());
- if (callData->argc() == 1) {
- functionValue = callData->args[0];
- } else if (callData->argc() >= 2) {
- functionThisValue = callData->args[0];
- functionValue = callData->args[1];
+ if (argc == 1) {
+ functionValue = argv[0];
+ } else if (argc >= 2) {
+ functionThisValue = argv[0];
+ functionValue = argv[1];
}
if (!functionValue)
@@ -1048,8 +1057,8 @@ void QObjectWrapper::destroyObject(bool lastCall)
if (ddata && ddata->ownContext) {
Q_ASSERT(ddata->ownContext == ddata->context);
ddata->ownContext->emitDestruction();
- ddata->ownContext = 0;
- ddata->context = 0;
+ ddata->ownContext = nullptr;
+ ddata->context = nullptr;
}
// This object is notionally destroyed now
ddata->isQueuedForDeletion = true;
@@ -1177,14 +1186,14 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index
} else {
- void *args[] = { 0 };
+ void *args[] = { nullptr };
object.metacall(callType, index, args);
return Encode::undefined();
}
}
-/*!
+/*
Returns the match score for converting \a actual to be of type \a conversionType. A
zero score means "perfect match" whereas a higher score is worse.
@@ -1341,7 +1350,7 @@ static inline int QMetaObject_methods(const QMetaObject *metaObject)
return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
}
-/*!
+/*
Returns the next related method, if one, or 0.
*/
static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
@@ -1350,7 +1359,7 @@ static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
const QQmlPropertyCache *propertyCache)
{
if (!current->isOverload())
- return 0;
+ return nullptr;
Q_ASSERT(!current->overrideIndexIsProperty());
@@ -1368,7 +1377,7 @@ static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
// If we've been called before with the same override index, then
// we can't go any further...
if (&dummy == current && dummy.coreIndex() == current->overrideIndex())
- return 0;
+ return nullptr;
QMetaMethod method = mo->method(current->overrideIndex());
dummy.load(method);
@@ -1403,7 +1412,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (data.hasArguments()) {
- int *args = 0;
+ int *args = nullptr;
QQmlMetaObject::ArgTypeStorage storage;
if (data.isConstructor())
@@ -1426,12 +1435,12 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
} else {
- return CallMethod(object, data.coreIndex(), returnType, 0, 0, engine, callArgs, callType);
+ return CallMethod(object, data.coreIndex(), returnType, 0, nullptr, engine, callArgs, callType);
}
}
-/*!
+/*
Resolve the overloaded method to call. The algorithm works conceptually like this:
1. Resolve the set of overloads it is *possible* to call.
Impossible overloads include those that have too many parameters or have parameters
@@ -1463,9 +1472,9 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
do {
QQmlMetaObject::ArgTypeStorage storage;
int methodArgumentCount = 0;
- int *methodArgTypes = 0;
+ int *methodArgTypes = nullptr;
if (attempt->hasArguments()) {
- int *args = object.methodParameterTypes(attempt->coreIndex(), &storage, 0);
+ int *args = object.methodParameterTypes(attempt->coreIndex(), &storage, nullptr);
if (!args) // Must be an unknown argument
continue;
@@ -1493,7 +1502,7 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
if (bestParameterScore == 0 && bestMatchScore == 0)
break; // We can't get better than that
- } while ((attempt = RelatedMethod(object, attempt, dummy, propertyCache)) != 0);
+ } while ((attempt = RelatedMethod(object, attempt, dummy, propertyCache)) != nullptr);
if (best.isValid()) {
return CallPrecise(object, best, engine, callArgs, callType);
@@ -1560,7 +1569,7 @@ void *CallArgument::dataPtr()
return stdVectorQModelIndexPtr;
else if (type != 0)
return (void *)&allocData;
- return 0;
+ return nullptr;
}
void CallArgument::initAsType(int callType)
@@ -1578,7 +1587,7 @@ void CallArgument::initAsType(int callType)
callType == QMetaType::Float) {
type = callType;
} else if (callType == QMetaType::QObjectStar) {
- qobjectPtr = 0;
+ qobjectPtr = nullptr;
type = callType;
} else if (callType == QMetaType::QString) {
qstringPtr = new (&allocData) QString();
@@ -1603,7 +1612,7 @@ void CallArgument::initAsType(int callType)
jsonValuePtr = new (&allocData) QJsonValue();
} else {
type = -1;
- qvariantPtr = new (&allocData) QVariant(callType, (void *)0);
+ qvariantPtr = new (&allocData) QVariant(callType, (void *)nullptr);
}
}
@@ -1655,7 +1664,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
qstringPtr = new (&allocData) QString(value.toQStringNoThrow());
type = callType;
} else if (callType == QMetaType::QObjectStar) {
- qobjectPtr = 0;
+ qobjectPtr = nullptr;
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
else if (const QV4::QQmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QQmlTypeWrapper>())
@@ -1672,14 +1681,14 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
uint length = array->getLength();
for (uint ii = 0; ii < length; ++ii) {
- QObject *o = 0;
+ QObject *o = nullptr;
qobjectWrapper = array->getIndexed(ii);
if (!!qobjectWrapper)
o = qobjectWrapper->object();
qlistPtr->append(o);
}
} else {
- QObject *o = 0;
+ QObject *o = nullptr;
if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
o = qobjectWrapper->object();
qlistPtr->append(o);
@@ -1736,7 +1745,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
qvariantPtr = new (&allocData) QVariant();
type = -1;
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : nullptr;
QVariant v = scope.engine->toVariant(value, callType);
if (v.userType() == callType) {
@@ -1749,12 +1758,12 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
if (!mo.isNull()) {
QObject *obj = ep->toQObject(v);
- if (obj != 0 && !QQmlMetaObject::canConvert(obj, mo))
- obj = 0;
+ if (obj != nullptr && !QQmlMetaObject::canConvert(obj, mo))
+ obj = nullptr;
*qvariantPtr = QVariant(callType, &obj);
} else {
- *qvariantPtr = QVariant(callType, (void *)0);
+ *qvariantPtr = QVariant(callType, (void *)nullptr);
}
}
}
@@ -1953,7 +1962,7 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value *
QQmlV4Function func(callData, rv, v4);
QQmlV4Function *funcptr = &func;
- void *args[] = { 0, &funcptr };
+ void *args[] = { nullptr, &funcptr };
object.metacall(QMetaObject::InvokeMetaMethod, method.coreIndex(), args);
return rv->asReturnedValue();
@@ -2083,11 +2092,11 @@ ReturnedValue QMetaObjectWrapper::callOverloadedConstructor(QV4::ExecutionEngine
for (int i = 0; i < numberOfConstructors; i++) {
const QQmlPropertyData & attempt = d()->constructors[i];
+ QQmlMetaObject::ArgTypeStorage storage;
int methodArgumentCount = 0;
- int *methodArgTypes = 0;
+ int *methodArgTypes = nullptr;
if (attempt.hasArguments()) {
- QQmlMetaObject::ArgTypeStorage storage;
- int *args = object.constructorParameterTypes(attempt.coreIndex(), &storage, 0);
+ int *args = object.constructorParameterTypes(attempt.coreIndex(), &storage, nullptr);
if (!args) // Must be an unknown argument
continue;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index c00e82e4fa..1455acc1b3 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -166,8 +166,8 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object(); }
- 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);
+ ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr, bool includeImports = false) const;
+ static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr);
static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
@@ -198,8 +198,8 @@ protected:
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- static ReturnedValue method_connect(const BuiltinFunction *, CallData *callData);
- static ReturnedValue method_disconnect(const BuiltinFunction *, CallData *callData);
+ static ReturnedValue method_connect(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_disconnect(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
private:
Q_NEVER_INLINE static ReturnedValue wrap_slowPath(ExecutionEngine *engine, QObject *object);
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index fb49def317..d99536829b 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -48,7 +48,7 @@ RegExpCache::~RegExpCache()
{
for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) {
if (RegExp *re = it.value().as<RegExp>())
- re->d()->cache = 0;
+ re->d()->cache = nullptr;
}
}
@@ -82,7 +82,7 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
return result->d();
Scope scope(engine);
- Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(pattern, ignoreCase, multiline, global));
+ Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline, global));
result->d()->cache = cache;
cachedValue.set(engine, result);
@@ -90,7 +90,7 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo
return result->d();
}
-void Heap::RegExp::init(const QString &pattern, bool ignoreCase, bool multiline, bool global)
+void Heap::RegExp::init(ExecutionEngine *engine, const QString &pattern, bool ignoreCase, bool multiline, bool global)
{
Base::init();
this->pattern = new QString(pattern);
@@ -100,13 +100,13 @@ void Heap::RegExp::init(const QString &pattern, bool ignoreCase, bool multiline,
valid = false;
- const char* error = 0;
+ const char* error = nullptr;
JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiLine, &error);
if (error)
return;
subPatternCount = yarrPattern.m_numSubpatterns;
#if ENABLE(YARR_JIT)
- if (!yarrPattern.m_containsBackreferences) {
+ if (!yarrPattern.m_containsBackreferences && engine->canJIT()) {
jitCode = new JSC::Yarr::YarrCodeBlock;
JSC::JSGlobalData dummy(internalClass->engine->regExpAllocator);
JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, *jitCode);
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 498468e165..56454f73d3 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -76,7 +76,7 @@ struct RegExpCacheKey;
namespace Heap {
struct RegExp : Base {
- void init(const QString& pattern, bool ignoreCase, bool multiline, bool global);
+ void init(ExecutionEngine *engine, const QString& pattern, bool ignoreCase, bool multiline, bool global);
void destroy();
QString *pattern;
@@ -100,7 +100,7 @@ struct RegExp : Base {
int captureCount() const { return subPatternCount + 1; }
};
-V4_ASSERT_IS_TRIVIAL(RegExp)
+Q_STATIC_ASSERT(std::is_trivial< RegExp >::value);
}
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index f95719b25f..000e2c3a7e 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -283,25 +283,25 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
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);
- ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, 0);
- ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, 0);
- ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, 0);
- ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, 0);
- ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, 0);
- ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, 0);
- ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, 0);
- ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, 0);
- ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, 0);
- ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, nullptr);
+ ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, nullptr);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
@@ -343,7 +343,7 @@ ReturnedValue RegExpPrototype::execFirstMatch(const FunctionObject *b, const Val
if (r->value()->captureCount()) {
int start = matchOffsets[0];
int end = matchOffsets[1];
- retVal = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ retVal = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined();
}
RegExpCtor::Data *dd = regExpCtor->d();
@@ -394,7 +394,7 @@ ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value
for (int i = 0; i < len; ++i) {
int start = matchOffsets[i * 2];
int end = matchOffsets[i * 2 + 1];
- v = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ v = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined();
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 240fba7905..04cad8ddb7 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -382,11 +382,11 @@ double RuntimeHelpers::stringToNumber(const QString &string)
{
const QStringRef s = QStringRef(&string).trimmed();
if (s.startsWith(QLatin1String("0x")) || s.startsWith(QLatin1String("0X")))
- return s.toLong(0, 16);
+ return s.toLong(nullptr, 16);
bool ok;
QByteArray ba = s.toLatin1();
const char *begin = ba.constData();
- const char *end = 0;
+ const char *end = nullptr;
double d = qstrtod(begin, &end, &ok);
if (end - begin != ba.size()) {
if (ba == "Infinity" || ba == "+Infinity")
@@ -457,7 +457,7 @@ Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Val
case Value::Undefined_Type:
case Value::Null_Type:
engine->throwTypeError();
- return 0;
+ return nullptr;
case Value::Boolean_Type:
return engine->newBooleanObject(value.booleanValue());
case Value::Managed_Type:
@@ -532,7 +532,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu
if (!sright->d()->length())
return sleft->asReturnedValue();
MemoryManager *mm = engine->memoryManager;
- return (mm->alloc<String>(sleft->d(), sright->d()))->asReturnedValue();
+ return (mm->alloc<ComplexString>(sleft->d(), sright->d()))->asReturnedValue();
}
double x = RuntimeHelpers::toNumber(pleft);
double y = RuntimeHelpers::toNumber(pright);
@@ -604,6 +604,14 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine,
return o->get(name);
}
+/* load element:
+
+ Managed *m = object.heapObject();
+ if (m)
+ return m->internalClass->getIndexed(m, index);
+ return getIndexedFallback(object, index);
+*/
+
ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index)
{
uint idx = 0;
@@ -672,7 +680,7 @@ bool Runtime::method_storeElement(ExecutionEngine *engine, const Value &object,
ReturnedValue Runtime::method_foreachIterator(ExecutionEngine *engine, const Value &in)
{
Scope scope(engine);
- ScopedObject o(scope, (Object *)0);
+ ScopedObject o(scope, (Object *)nullptr);
if (!in.isNullOrUndefined())
o = in.toObject(engine);
return engine->newForEachIteratorObject(o)->asReturnedValue();
@@ -1090,6 +1098,37 @@ ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &fu
return static_cast<const FunctionObject &>(func).call(nullptr, argv, argc);
}
+ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine, Value *base,
+ int propertyIndex, Value *argv, int argc)
+{
+ Scope scope(engine);
+ ScopedFunctionObject fo(scope, method_loadQmlScopeObjectProperty(engine, *base, propertyIndex,
+ /*captureRequired*/true));
+ if (!fo) {
+ QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex);
+ return engine->throwTypeError(error);
+ }
+
+ QObject *qmlScopeObj = static_cast<QmlContext *>(base)->d()->qml()->scopeObject;
+ ScopedValue qmlScopeValue(scope, QObjectWrapper::wrap(engine, qmlScopeObj));
+ return fo->call(qmlScopeValue, argv, argc);
+}
+
+ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engine, Value *base,
+ int propertyIndex, Value *argv, int argc)
+{
+ Scope scope(engine);
+ ScopedFunctionObject fo(scope, method_loadQmlContextObjectProperty(engine, *base, propertyIndex,
+ /*captureRequired*/true));
+ if (!fo) {
+ QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex);
+ return engine->throwTypeError(error);
+ }
+
+ QObject *qmlContextObj = static_cast<QmlContext *>(base)->d()->qml()->context->contextData()->contextObject;
+ ScopedValue qmlContextValue(scope, QObjectWrapper::wrap(engine, qmlContextObj));
+ return fo->call(qmlContextValue, argv, argc);
+}
ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &function, Value *argv, int argc)
{
@@ -1160,7 +1199,7 @@ ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int e
{
ExecutionEngine *e = parent->engine();
return parent->newCatchContext(e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex],
- e->catchException(0))->asReturnedValue();
+ e->catchException(nullptr))->asReturnedValue();
}
void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
@@ -1260,7 +1299,7 @@ ReturnedValue Runtime::method_loadQmlIdObject(ExecutionEngine *engine, const Val
if (!context || index >= (uint)context->idValueCount)
return Encode::undefined();
- QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : nullptr;
if (ep && ep->propertyCapture)
ep->propertyCapture->captureProperty(&context->idValues[index].bindings);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index ea31dfd08b..2956a4a463 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -188,6 +188,8 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, loadQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \
F(ReturnedValue, loadQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \
F(ReturnedValue, loadQmlIdObject, (ExecutionEngine *engine, const Value &context, uint index)) \
+ F(ReturnedValue, callQmlScopeObjectProperty, (ExecutionEngine *engine, Value *base, int propertyIndex, Value *argv, int argc)) \
+ F(ReturnedValue, callQmlContextObjectProperty, (ExecutionEngine *engine, Value *base, int propertyIndex, Value *argv, int argc)) \
\
F(void, storeQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)) \
F(void, storeQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)) \
diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp
index 9c115099b5..fe18ddf9ed 100644
--- a/src/qml/jsruntime/qv4runtimecodegen.cpp
+++ b/src/qml/jsruntime/qv4runtimecodegen.cpp
@@ -49,15 +49,16 @@ void RuntimeCodegen::generateFromFunctionExpression(const QString &fileName,
{
_module = module;
_module->fileName = fileName;
- _context = 0;
+ _module->finalUrl = fileName;
+ _context = nullptr;
Compiler::ScanFunctions scan(this, sourceCode, Compiler::GlobalCode);
// fake a global environment
- scan.enterEnvironment(0, Compiler::FunctionCode);
+ scan.enterEnvironment(nullptr, Compiler::FunctionCode);
scan(ast);
scan.leaveEnvironment();
- int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
+ int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : nullptr);
_module->rootContext = _module->functions.at(index);
}
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index afb5c21d36..bb20f384b3 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -209,7 +209,7 @@ struct Scoped
enum ConvertType { Convert };
QML_NEARLY_ALWAYS_INLINE void setPointer(const Managed *p) {
- ptr->setM(p ? p->m() : 0);
+ ptr->setM(p ? p->m() : nullptr);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope)
@@ -244,7 +244,7 @@ struct Scoped
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value *v)
{
ptr = scope.engine->jsAlloca(1);
- setPointer(v ? v->as<T>() : 0);
+ setPointer(v ? v->as<T>() : nullptr);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, T *t)
@@ -290,7 +290,7 @@ struct Scoped
return *this;
}
Scoped<T> &operator=(Value *v) {
- setPointer(v ? v->as<T>() : 0);
+ setPointer(v ? v->as<T>() : nullptr);
return *this;
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 901f2574da..bb6608bec0 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -62,14 +62,14 @@ using namespace QV4;
Script::Script(ExecutionEngine *v4, QmlContext *qml, CompiledData::CompilationUnit *compilationUnit)
: line(1), column(0), context(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , compilationUnit(compilationUnit), vmFunction(0), parseAsBinding(true)
+ , compilationUnit(compilationUnit), vmFunction(nullptr), parseAsBinding(true)
{
if (qml)
qmlContext.set(v4, *qml);
parsed = true;
- vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : 0;
+ vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : nullptr;
}
Script::~Script()
@@ -88,7 +88,7 @@ void Script::parse()
ExecutionEngine *v4 = context->engine();
Scope valueScope(v4);
- Module module(v4->debugger() != 0);
+ Module module(v4->debugger() != nullptr);
Engine ee, *engine = &ee;
Lexer lexer(engine);
@@ -121,7 +121,7 @@ void Script::parse()
RuntimeCodegen cg(v4, &jsGenerator, strictMode);
if (inheritContext)
cg.setUseFastLookups(false);
- cg.generateFromProgram(sourceFile, sourceCode, program, &module, compilationMode);
+ cg.generateFromProgram(sourceFile, sourceFile, sourceCode, program, &module, compilationMode);
if (v4->hasException)
return;
@@ -149,10 +149,10 @@ ReturnedValue Script::run()
if (qmlContext.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- return vmFunction->call(engine->globalObject, 0, 0, context);
+ return vmFunction->call(engine->globalObject, nullptr, 0, context);
} else {
Scoped<QmlContext> qml(valueScope, qmlContext.value());
- return vmFunction->call(0, 0, 0, qml);
+ return vmFunction->call(nullptr, nullptr, 0, qml);
}
}
@@ -164,8 +164,8 @@ Function *Script::function()
}
QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compiler::Module *module, Compiler::JSUnitGenerator *unitGenerator,
- const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors,
- Directives *directivesCollector)
+ const QString &fileName, const QString &finalUrl, const QString &source,
+ QList<QQmlError> *reportedErrors, Directives *directivesCollector)
{
using namespace QV4::Compiler;
using namespace QQmlJS::AST;
@@ -184,12 +184,12 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compi
const auto diagnosticMessages = parser.diagnosticMessages();
for (const DiagnosticMessage &m : diagnosticMessages) {
if (m.isWarning()) {
- qWarning("%s:%d : %s", qPrintable(url.toString()), m.loc.startLine, qPrintable(m.message));
+ qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
continue;
}
QQmlError error;
- error.setUrl(url);
+ error.setUrl(QUrl(fileName));
error.setDescription(m.message);
error.setLine(m.loc.startLine);
error.setColumn(m.loc.startColumn);
@@ -199,29 +199,50 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compi
if (!errors.isEmpty()) {
if (reportedErrors)
*reportedErrors << errors;
- return 0;
+ return nullptr;
}
Program *program = AST::cast<Program *>(parser.rootNode());
if (!program) {
// if parsing was successful, and we have no program, then
// we're done...:
- return 0;
+ return nullptr;
}
Codegen cg(unitGenerator, /*strict mode*/false);
cg.setUseFastLookups(false);
- cg.generateFromProgram(url.toString(), source, program, module, GlobalCode);
+ cg.generateFromProgram(fileName, finalUrl, source, program, module, GlobalCode);
errors = cg.qmlErrors();
if (!errors.isEmpty()) {
if (reportedErrors)
*reportedErrors << errors;
- return 0;
+ return nullptr;
}
return cg.generateCompilationUnit(/*generate unit data*/false);
}
+Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl)
+{
+ if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(originalUrl)) {
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> jsUnit;
+ jsUnit.adopt(new QV4::CompiledData::CompilationUnit(cachedUnit));
+ return new QV4::Script(engine, qmlContext, jsUnit);
+ }
+
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly))
+ return nullptr;
+
+ QByteArray data = f.readAll();
+ QString sourceCode = QString::fromUtf8(data);
+ QmlIR::Document::removeScriptPragmas(sourceCode);
+
+ auto result = new QV4::Script(engine, qmlContext, sourceCode, originalUrl.toString());
+ result->parse();
+ return result;
+}
+
QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext)
{
QV4::Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 158d21c69d..24291b9aa6 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -68,11 +68,11 @@ struct Q_QML_EXPORT Script {
Script(ExecutionContext *scope, QV4::Compiler::CompilationMode mode, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, context(scope), strictMode(false), inheritContext(false), parsed(false), compilationMode(mode)
- , vmFunction(0), parseAsBinding(false) {}
+ , vmFunction(nullptr), parseAsBinding(false) {}
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)
, context(engine->rootContext()), strictMode(false), inheritContext(true), parsed(false)
- , vmFunction(0), parseAsBinding(true) {
+ , vmFunction(nullptr), parseAsBinding(true) {
if (qml)
qmlContext.set(engine, *qml);
}
@@ -97,8 +97,11 @@ struct Q_QML_EXPORT Script {
Function *function();
- static QQmlRefPointer<CompiledData::CompilationUnit> precompile(QV4::Compiler::Module *module, Compiler::JSUnitGenerator *unitGenerator, const QUrl &url, const QString &source,
- QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
+ static QQmlRefPointer<CompiledData::CompilationUnit> precompile(
+ QV4::Compiler::Module *module, Compiler::JSUnitGenerator *unitGenerator,
+ const QString &fileName, const QString &finalUrl, const QString &source,
+ QList<QQmlError> *reportedErrors = nullptr, QQmlJS::Directives *directivesCollector = nullptr);
+ static Script *createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlContext, const QString &fileName, const QUrl &originalUrl);
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 78cd7529d8..7d29d0b517 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -340,7 +340,7 @@ public:
void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- name->setM(0);
+ name->setM(nullptr);
*index = UINT_MAX;
if (d()->isReference) {
@@ -420,11 +420,10 @@ public:
ScopedFunctionObject compare(scope, m_compareFn);
if (!compare)
return m_v4->throwTypeError();
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = convertElementToValue(m_v4, lhs);
- jsCallData->args[1] = convertElementToValue(m_v4, rhs);
- *jsCallData->thisObject = m_v4->globalObject;
- QV4::ScopedValue result(scope, compare->call(jsCallData));
+ Value *argv = scope.alloc(2);
+ argv[0] = convertElementToValue(m_v4, lhs);
+ argv[1] = convertElementToValue(m_v4, rhs);
+ QV4::ScopedValue result(scope, compare->call(m_v4->globalObject, argv, 2));
return result->toNumber() < 0;
}
@@ -433,7 +432,7 @@ public:
const QV4::Value *m_compareFn;
};
- void sort(const BuiltinFunction *, Scope &scope, CallData *callData)
+ void sort(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
if (d()->isReference) {
if (!d()->object)
@@ -441,8 +440,8 @@ public:
loadReference();
}
- if (callData->argc() == 1 && callData->args[0].as<FunctionObject>()) {
- CompareFunctor cf(scope.engine, callData->args[0]);
+ if (argc == 1 && argv[0].as<FunctionObject>()) {
+ CompareFunctor cf(f->engine(), argv[0]);
std::sort(d()->container->begin(), d()->container->end(), cf);
} else {
DefaultCompareFunctor cf;
@@ -453,10 +452,10 @@ public:
storeReference();
}
- static QV4::ReturnedValue method_get_length(const BuiltinFunction *b, CallData *callData)
+ static QV4::ReturnedValue method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
QV4::Scope scope(b);
- QV4::Scoped<QQmlSequence<Container> > This(scope, callData->thisObject.as<QQmlSequence<Container> >());
+ QV4::Scoped<QQmlSequence<Container>> This(scope, thisObject->as<QQmlSequence<Container> >());
if (!This)
THROW_TYPE_ERROR();
@@ -468,14 +467,14 @@ public:
RETURN_RESULT(Encode(qint32(This->d()->container->size())));
}
- static QV4::ReturnedValue method_set_length(const BuiltinFunction *b, CallData *callData)
+ static QV4::ReturnedValue method_set_length(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlSequence<Container> > This(scope, callData->thisObject.as<QQmlSequence<Container> >());
+ QV4::Scope scope(f);
+ QV4::Scoped<QQmlSequence<Container>> This(scope, thisObject->as<QQmlSequence<Container> >());
if (!This)
THROW_TYPE_ERROR();
- quint32 newLength = callData->args[0].toUInt32();
+ quint32 newLength = argc ? argv[0].toUInt32() : 0;
/* Qt containers have int (rather than uint) allowable indexes. */
if (newLength > INT_MAX) {
generateWarning(scope.engine, QLatin1String("Index out of range during length set"));
@@ -536,7 +535,7 @@ public:
{
Q_ASSERT(d()->object);
Q_ASSERT(d()->isReference);
- void *a[] = { d()->container, 0 };
+ void *a[] = { d()->container, nullptr };
QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a);
}
@@ -546,7 +545,7 @@ public:
Q_ASSERT(d()->isReference);
int status = -1;
QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding;
- void *a[] = { d()->container, 0, &status, &flags };
+ void *a[] = { d()->container, nullptr, &status, &flags };
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
@@ -652,24 +651,24 @@ void SequencePrototype::init()
}
#undef REGISTER_QML_SEQUENCE_METATYPE
-ReturnedValue SequencePrototype::method_valueOf(const BuiltinFunction *f, CallData *callData)
+ReturnedValue SequencePrototype::method_valueOf(const FunctionObject *f, const Value *thisObject, const Value *, int)
{
- return Encode(callData->thisObject.toString(f->engine()));
+ return Encode(thisObject->toString(f->engine()));
}
-ReturnedValue SequencePrototype::method_sort(const BuiltinFunction *b, CallData *callData)
+ReturnedValue SequencePrototype::method_sort(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
- QV4::ScopedObject o(scope, callData->thisObject);
+ QV4::ScopedObject o(scope, thisObject);
if (!o || !o->isListType())
THROW_TYPE_ERROR();
- if (callData->argc() >= 2)
+ if (argc >= 2)
return o.asReturnedValue();
#define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \
- s->sort(b, scope, callData); \
+ s->sort(b, thisObject, argv, argc); \
} else
FOREACH_QML_SEQUENCE_TYPE(CALL_SORT)
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 169a48c2f9..e9bef2f604 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -68,8 +68,8 @@ struct SequencePrototype : public QV4::Object
V4_PROTOTYPE(arrayPrototype)
void init();
- static ReturnedValue method_valueOf(const BuiltinFunction *f, CallData *callData);
- static ReturnedValue method_sort(const BuiltinFunction *, CallData *callData);
+ static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_sort(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 8f6aa6723c..2a3e28bf63 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -89,20 +89,20 @@ const SparseArrayNode *SparseArrayNode::previousNode() const
SparseArrayNode *SparseArrayNode::copy(SparseArray *d) const
{
- SparseArrayNode *n = d->createNode(size_left, 0, false);
+ SparseArrayNode *n = d->createNode(size_left, nullptr, false);
n->value = value;
n->setColor(color());
if (left) {
n->left = left->copy(d);
n->left->setParent(n);
} else {
- n->left = 0;
+ n->left = nullptr;
}
if (right) {
n->right = right->copy(d);
n->right->setParent(n);
} else {
- n->right = 0;
+ n->right = nullptr;
}
return n;
}
@@ -119,7 +119,7 @@ void SparseArray::rotateLeft(SparseArrayNode *x)
SparseArrayNode *&root = header.left;
SparseArrayNode *y = x->right;
x->right = y->left;
- if (y->left != 0)
+ if (y->left != nullptr)
y->left->setParent(x);
y->setParent(x->parent());
if (x == root)
@@ -146,7 +146,7 @@ void SparseArray::rotateRight(SparseArrayNode *x)
SparseArrayNode *&root = header.left;
SparseArrayNode *y = x->left;
x->left = y->right;
- if (y->right != 0)
+ if (y->right != nullptr)
y->right->setParent(x);
y->setParent(x->parent());
if (x == root)
@@ -209,7 +209,7 @@ void SparseArray::deleteNode(SparseArrayNode *z)
SparseArrayNode *y = z;
SparseArrayNode *x;
SparseArrayNode *x_parent;
- if (y->left == 0) {
+ if (y->left == nullptr) {
x = y->right;
if (y == mostLeftNode) {
if (x)
@@ -217,11 +217,11 @@ void SparseArray::deleteNode(SparseArrayNode *z)
else
mostLeftNode = y->parent();
}
- } else if (y->right == 0) {
+ } else if (y->right == nullptr) {
x = y->left;
} else {
y = y->right;
- while (y->left != 0)
+ while (y->left != nullptr)
y = y->left;
x = y->right;
}
@@ -261,7 +261,7 @@ void SparseArray::deleteNode(SparseArrayNode *z)
y->size_left = 0;
}
if (y->color() != SparseArrayNode::Red) {
- while (x != root && (x == 0 || x->color() == SparseArrayNode::Black)) {
+ while (x != root && (x == nullptr || x->color() == SparseArrayNode::Black)) {
if (x == x_parent->left) {
SparseArrayNode *w = x_parent->right;
if (w->color() == SparseArrayNode::Red) {
@@ -270,13 +270,13 @@ void SparseArray::deleteNode(SparseArrayNode *z)
rotateLeft(x_parent);
w = x_parent->right;
}
- if ((w->left == 0 || w->left->color() == SparseArrayNode::Black) &&
- (w->right == 0 || w->right->color() == SparseArrayNode::Black)) {
+ if ((w->left == nullptr || w->left->color() == SparseArrayNode::Black) &&
+ (w->right == nullptr || w->right->color() == SparseArrayNode::Black)) {
w->setColor(SparseArrayNode::Red);
x = x_parent;
x_parent = x_parent->parent();
} else {
- if (w->right == 0 || w->right->color() == SparseArrayNode::Black) {
+ if (w->right == nullptr || w->right->color() == SparseArrayNode::Black) {
if (w->left)
w->left->setColor(SparseArrayNode::Black);
w->setColor(SparseArrayNode::Red);
@@ -298,13 +298,13 @@ void SparseArray::deleteNode(SparseArrayNode *z)
rotateRight(x_parent);
w = x_parent->left;
}
- if ((w->right == 0 || w->right->color() == SparseArrayNode::Black) &&
- (w->left == 0 || w->left->color() == SparseArrayNode::Black)) {
+ if ((w->right == nullptr || w->right->color() == SparseArrayNode::Black) &&
+ (w->left == nullptr || w->left->color() == SparseArrayNode::Black)) {
w->setColor(SparseArrayNode::Red);
x = x_parent;
x_parent = x_parent->parent();
} else {
- if (w->left == 0 || w->left->color() == SparseArrayNode::Black) {
+ if (w->left == nullptr || w->left->color() == SparseArrayNode::Black) {
if (w->right)
w->right->setColor(SparseArrayNode::Black);
w->setColor(SparseArrayNode::Red);
@@ -363,8 +363,8 @@ SparseArrayNode *SparseArray::createNode(uint sl, SparseArrayNode *parent, bool
Q_CHECK_PTR(node);
node->p = (quintptr)parent;
- node->left = 0;
- node->right = 0;
+ node->left = nullptr;
+ node->right = nullptr;
node->size_left = sl;
node->value = UINT_MAX;
++numEntries;
@@ -395,21 +395,23 @@ void SparseArray::freeTree(SparseArrayNode *root, int alignment)
SparseArray::SparseArray()
: numEntries(0)
{
+ freeList = Primitive::emptyValue(UINT_MAX).asReturnedValue();
header.p = 0;
- header.left = 0;
- header.right = 0;
+ header.left = nullptr;
+ header.right = nullptr;
mostLeftNode = &header;
}
SparseArray::SparseArray(const SparseArray &other)
{
header.p = 0;
- header.right = 0;
+ header.right = nullptr;
if (other.header.left) {
header.left = other.header.left->copy(this);
header.left->setParent(&header);
recalcMostLeftNode();
}
+ freeList = other.freeList;
}
SparseArrayNode *SparseArray::insert(uint akey)
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 2e4ac883f2..51869b259f 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -109,7 +109,7 @@ struct SparseArrayNode
inline SparseArrayNode *SparseArrayNode::lowerBound(uint akey)
{
SparseArrayNode *n = this;
- SparseArrayNode *last = 0;
+ SparseArrayNode *last = nullptr;
while (n) {
if (akey <= n->size_left) {
last = n;
@@ -126,7 +126,7 @@ inline SparseArrayNode *SparseArrayNode::lowerBound(uint akey)
inline SparseArrayNode *SparseArrayNode::upperBound(uint akey)
{
SparseArrayNode *n = this;
- SparseArrayNode *last = 0;
+ SparseArrayNode *last = nullptr;
while (n) {
if (akey < n->size_left) {
last = n;
@@ -150,6 +150,8 @@ struct Q_QML_EXPORT SparseArray
}
SparseArray(const SparseArray &other);
+
+ ReturnedValue freeList;
private:
SparseArray &operator=(const SparseArray &other);
@@ -221,7 +223,7 @@ inline SparseArrayNode *SparseArray::findNode(uint akey) const
}
}
- return 0;
+ return nullptr;
}
inline uint SparseArray::pop_front()
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index b38b01c9f7..447992ebec 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -55,9 +55,16 @@ using namespace QV4;
void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
{
String *s = static_cast<String *>(that);
- if (s->largestSubLength) {
- s->left->mark(markStack);
- s->right->mark(markStack);
+ if (s->subtype < StringType_Complex)
+ return;
+
+ ComplexString *cs = static_cast<ComplexString *>(s);
+ if (cs->subtype == StringType_AddedString) {
+ cs->left->mark(markStack);
+ cs->right->mark(markStack);
+ } else {
+ Q_ASSERT(cs->subtype == StringType_SubString);
+ cs->left->mark(markStack);
}
}
@@ -84,37 +91,45 @@ void Heap::String::init(const QString &t)
text = const_cast<QString &>(t).data_ptr();
text->ref.ref();
- identifier = 0;
- stringHash = UINT_MAX;
- largestSubLength = 0;
- len = text->size;
}
-void Heap::String::init(String *l, String *r)
+void Heap::ComplexString::init(String *l, String *r)
{
Base::init();
- subtype = String::StringType_Unknown;
+ subtype = String::StringType_AddedString;
left = l;
right = r;
- stringHash = UINT_MAX;
- largestSubLength = qMax(l->largestSubLength, r->largestSubLength);
- len = l->len + r->len;
- Q_ASSERT(largestSubLength <= len);
-
- if (!l->largestSubLength && l->len > largestSubLength)
- largestSubLength = l->len;
- if (!r->largestSubLength && r->len > largestSubLength)
- largestSubLength = r->len;
+ len = left->length() + right->length();
+ if (left->subtype >= StringType_Complex)
+ largestSubLength = static_cast<ComplexString *>(left)->largestSubLength;
+ else
+ largestSubLength = left->length();
+ if (right->subtype >= StringType_Complex)
+ largestSubLength = qMax(largestSubLength, static_cast<ComplexString *>(right)->largestSubLength);
+ else
+ largestSubLength = qMax(largestSubLength, right->length());
// make sure we don't get excessive depth in our strings
if (len > 256 && len >= 2*largestSubLength)
simplifyString();
}
+void Heap::ComplexString::init(Heap::String *ref, int from, int len)
+{
+ Q_ASSERT(ref->length() >= from + len);
+ Base::init();
+
+ subtype = String::StringType_SubString;
+
+ left = ref;
+ this->from = from;
+ this->len = len;
+}
+
void Heap::String::destroy() {
- if (!largestSubLength) {
+ if (text) {
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar));
if (!text->ref.deref())
QStringData::deallocate(text);
@@ -126,7 +141,7 @@ uint String::toUInt(bool *ok) const
{
*ok = true;
- if (subtype() == Heap::String::StringType_Unknown)
+ if (subtype() >= Heap::String::StringType_Unknown)
d()->createHashValue();
if (subtype() == Heap::String::StringType_ArrayIndex)
return d()->stringHash;
@@ -142,15 +157,15 @@ uint String::toUInt(bool *ok) const
void String::makeIdentifierImpl() const
{
- if (d()->largestSubLength)
+ if (!d()->text)
d()->simplifyString();
- Q_ASSERT(!d()->largestSubLength);
+ Q_ASSERT(d()->text);
engine()->identifierTable->identifier(this);
}
void Heap::String::simplifyString() const
{
- Q_ASSERT(largestSubLength);
+ Q_ASSERT(!text);
int l = length();
QString result(l, Qt::Uninitialized);
@@ -158,9 +173,33 @@ void Heap::String::simplifyString() const
append(this, ch);
text = result.data_ptr();
text->ref.ref();
- identifier = 0;
- largestSubLength = 0;
+ const ComplexString *cs = static_cast<const ComplexString *>(this);
+ identifier = nullptr;
+ cs->left = cs->right = nullptr;
+
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar));
+ subtype = StringType_Unknown;
+}
+
+bool Heap::String::startsWithUpper() const
+{
+ if (subtype == StringType_AddedString)
+ return static_cast<const Heap::ComplexString *>(this)->left->startsWithUpper();
+
+ const Heap::String *str = this;
+ int offset = 0;
+ if (subtype == StringType_SubString) {
+ const ComplexString *cs = static_cast<const Heap::ComplexString *>(this);
+ if (!cs->len)
+ return false;
+ // simplification here is not ideal, but hopefully not a common case.
+ if (cs->left->subtype >= Heap::String::StringType_Complex)
+ cs->left->simplifyString();
+ str = cs->left;
+ offset = cs->from;
+ }
+ Q_ASSERT(str->subtype < Heap::String::StringType_Complex);
+ return str->text->size > offset && QChar::isUpper(str->text->data()[offset]);
}
void Heap::String::append(const String *data, QChar *ch)
@@ -173,11 +212,16 @@ void Heap::String::append(const String *data, QChar *ch)
const String *item = worklist.back();
worklist.pop_back();
- if (item->largestSubLength) {
- worklist.push_back(item->right);
- worklist.push_back(item->left);
+ if (item->subtype == StringType_AddedString) {
+ const ComplexString *cs = static_cast<const ComplexString *>(item);
+ worklist.push_back(cs->right);
+ worklist.push_back(cs->left);
+ } else if (item->subtype == StringType_SubString) {
+ const ComplexString *cs = static_cast<const ComplexString *>(item);
+ memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*sizeof(QChar));
+ ch += cs->len;
} else {
- memcpy(ch, item->text->data(), item->text->size * sizeof(QChar));
+ memcpy(static_cast<void *>(ch), static_cast<const void *>(item->text->data()), item->text->size * sizeof(QChar));
ch += item->text->size;
}
}
@@ -185,9 +229,9 @@ void Heap::String::append(const String *data, QChar *ch)
void Heap::String::createHashValue() const
{
- if (largestSubLength)
+ if (!text)
simplifyString();
- Q_ASSERT(!largestSubLength);
+ Q_ASSERT(text);
const QChar *ch = reinterpret_cast<const QChar *>(text->data());
const QChar *end = ch + text->size;
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 85345aca4d..5466cc274d 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -67,35 +67,32 @@ namespace Heap {
struct Q_QML_PRIVATE_EXPORT String : Base {
static void markObjects(Heap::Base *that, MarkStack *markStack);
enum StringType {
- StringType_Unknown,
StringType_Regular,
- StringType_ArrayIndex
+ StringType_ArrayIndex,
+ StringType_Unknown,
+ StringType_AddedString,
+ StringType_SubString,
+ StringType_Complex = StringType_AddedString
};
#ifndef V4_BOOTSTRAP
void init(const QString &text);
- void init(String *l, String *n);
void destroy();
void simplifyString() const;
- int length() const {
- Q_ASSERT((largestSubLength &&
- (len == left->len + right->len)) ||
- len == (uint)text->size);
- return len;
- }
+ int length() const;
std::size_t retainedTextSize() const {
- return largestSubLength ? 0 : (std::size_t(text->size) * sizeof(QChar));
+ return subtype >= StringType_Complex ? 0 : (std::size_t(text->size) * sizeof(QChar));
}
void createHashValue() const;
inline unsigned hashValue() const {
- if (subtype == StringType_Unknown)
+ if (subtype >= StringType_Unknown)
createHashValue();
- Q_ASSERT(!largestSubLength);
+ Q_ASSERT(subtype < StringType_Complex);
return stringHash;
}
inline QString toQString() const {
- if (largestSubLength)
+ if (subtype >= StringType_Complex)
simplifyString();
QStringDataPtr ptr = { text };
text->ref.ref();
@@ -106,7 +103,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
return true;
if (hashValue() != other->hashValue())
return false;
- Q_ASSERT(!largestSubLength);
+ Q_ASSERT(subtype < StringType_Complex);
if (identifier && identifier == other->identifier)
return true;
if (subtype == Heap::String::StringType_ArrayIndex && other->subtype == Heap::String::StringType_ArrayIndex)
@@ -115,23 +112,37 @@ struct Q_QML_PRIVATE_EXPORT String : Base {
return toQString() == other->toQString();
}
- union {
- mutable QStringData *text;
- mutable String *left;
- };
- union {
- mutable Identifier *identifier;
- mutable String *right;
- };
+ bool startsWithUpper() const;
+
+ mutable QStringData *text;
+ mutable Identifier *identifier;
mutable uint subtype;
mutable uint stringHash;
- mutable uint largestSubLength;
- uint len;
private:
static void append(const String *data, QChar *ch);
#endif
};
-V4_ASSERT_IS_TRIVIAL(String)
+Q_STATIC_ASSERT(std::is_trivial< String >::value);
+
+#ifndef V4_BOOTSTRAP
+struct ComplexString : String {
+ void init(String *l, String *n);
+ void init(String *ref, int from, int len);
+ mutable String *left;
+ mutable String *right;
+ union {
+ mutable int largestSubLength;
+ int from;
+ };
+ int len;
+};
+Q_STATIC_ASSERT(std::is_trivial< ComplexString >::value);
+
+inline
+int String::length() const {
+ return text ? text->size : static_cast<const ComplexString *>(this)->len;
+}
+#endif
}
@@ -167,9 +178,9 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
return d()->hashValue();
}
uint asArrayIndex() const {
- if (subtype() == Heap::String::StringType_Unknown)
+ if (subtype() >= Heap::String::StringType_Unknown)
d()->createHashValue();
- Q_ASSERT(!d()->largestSubLength);
+ Q_ASSERT(d()->subtype < Heap::String::StringType_Complex);
if (subtype() == Heap::String::StringType_ArrayIndex)
return d()->stringHash;
return UINT_MAX;
@@ -197,12 +208,7 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
return calculateHashValue(ch, end, subtype);
}
- bool startsWithUpper() const {
- const String::Data *l = d();
- while (l->largestSubLength)
- l = l->left;
- return l->text->size && QChar::isUpper(l->text->data()[0]);
- }
+ bool startsWithUpper() const { return d()->startsWithUpper(); }
Identifier *identifier() const { return d()->identifier; }
@@ -216,7 +222,7 @@ public:
private:
static inline uint toUInt(const QChar *ch) { return ch->unicode(); }
- static inline uint toUInt(const char *ch) { return *ch; }
+ static inline uint toUInt(const char *ch) { return static_cast<unsigned char>(*ch); }
template <typename T>
static inline uint toArrayIndex(const T *ch, const T *end)
@@ -263,12 +269,22 @@ public:
}
};
+#ifndef V4_BOOTSTRAP
+struct ComplexString : String {
+ typedef QV4::Heap::ComplexString Data;
+ QV4::Heap::ComplexString *d_unchecked() const { return static_cast<QV4::Heap::ComplexString *>(m()); }
+ QV4::Heap::ComplexString *d() const {
+ QV4::Heap::ComplexString *dptr = d_unchecked();
+ dptr->_checkIsInitialized();
+ return dptr;
+ }
+};
+
template<>
inline const String *Value::as() const {
- return isManaged() && m()->vtable()->isString ? static_cast<const String *>(this) : 0;
+ return isManaged() && m()->vtable()->isString ? static_cast<const String *>(this) : nullptr;
}
-#ifndef V4_BOOTSTRAP
template<>
inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
{
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index efab51ec53..e5a02fdc22 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -86,13 +86,13 @@ Heap::String *Heap::StringObject::getIndex(uint index) const
{
QString str = string->toQString();
if (index >= (uint)str.length())
- return 0;
+ return nullptr;
return internalClass->engine->newString(str.mid(index, 1));
}
uint Heap::StringObject::length() const
{
- return string->len;
+ return string->length();
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
@@ -109,7 +109,7 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs)
{
- name->setM(0);
+ name->setM(nullptr);
StringObject *s = static_cast<StringObject *>(m);
uint slen = s->d()->string->toQString().length();
if (it->arrayIndex <= slen) {
@@ -200,6 +200,15 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
defineDefaultProperty(QStringLiteral("trim"), method_trim);
}
+static Heap::String *thisAsString(ExecutionEngine *v4, const Value *thisObject)
+{
+ if (String *s = thisObject->stringValue())
+ return s->d();
+ if (const StringObject *thisString = thisObject->as<StringObject>())
+ return thisString->d()->string;
+ return thisObject->toString(v4);
+}
+
static QString getThisString(ExecutionEngine *v4, const Value *thisObject)
{
if (String *s = thisObject->stringValue())
@@ -649,11 +658,13 @@ ReturnedValue StringPrototype::method_search(const FunctionObject *b, const Valu
ReturnedValue StringPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
ExecutionEngine *v4 = b->engine();
- const QString text = getThisString(v4, thisObject);
+ Scope scope(v4);
+ ScopedString s(scope, thisAsString(v4, thisObject));
if (v4->hasException)
return QV4::Encode::undefined();
+ Q_ASSERT(s);
- const double length = text.length();
+ const double length = s->d()->length();
double start = argc ? argv[0].toInteger() : 0;
double end = (argc < 2 || argv[1].isUndefined())
@@ -673,7 +684,7 @@ ReturnedValue StringPrototype::method_slice(const FunctionObject *b, const Value
const int intEnd = int(end);
int count = qMax(0, intEnd - intStart);
- return Encode(v4->newString(text.mid(intStart, count)));
+ return Encode(v4->memoryManager->alloc<ComplexString>(s->d(), intStart, count));
}
ReturnedValue StringPrototype::method_split(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
@@ -706,7 +717,7 @@ ReturnedValue StringPrototype::method_split(const FunctionObject *b, const Value
Scoped<RegExpObject> re(scope, separatorValue);
if (re) {
if (re->value()->pattern->isEmpty()) {
- re = (RegExpObject *)0;
+ re = (RegExpObject *)nullptr;
separatorValue = scope.engine->newString();
}
}
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 4ba31f9b6e..ea1532b8ce 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -399,10 +399,10 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
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));
- defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
- defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
- defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
- defineAccessorProperty(QStringLiteral("length"), method_get_length, 0);
+ defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, nullptr);
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr);
+ defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, nullptr);
+ defineAccessorProperty(QStringLiteral("length"), method_get_length, nullptr);
defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
defineDefaultProperty(QStringLiteral("set"), method_set, 1);
@@ -514,7 +514,7 @@ ReturnedValue TypedArrayPrototype::method_set(const FunctionObject *b, const Val
RETURN_UNDEFINED();
}
- char *srcCopy = 0;
+ char *srcCopy = nullptr;
if (buffer->d() == srcBuffer->d()) {
// same buffer, need to take a temporary copy, to not run into problems
srcCopy = new char[srcTypedArray->d()->byteLength];
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 52d9f23afd..97ed13cd91 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -57,6 +57,8 @@
#include "qv4global_p.h"
#include <private/qv4heap_p.h>
+#include <private/qnumeric_p.h>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -322,6 +324,8 @@ public:
return d;
}
QML_NEARLY_ALWAYS_INLINE void setDouble(double d) {
+ if (qt_is_nan(d))
+ d = qt_qnan();
memcpy(&_val, &d, 8);
_val ^= NaNEncodeMask;
Q_ASSERT(isDouble());
@@ -422,7 +426,7 @@ public:
template <typename T>
const T *as() const {
if (!isManaged())
- return 0;
+ return nullptr;
Q_ASSERT(m()->vtable());
#if !defined(QT_NO_QOBJECT_CHECK)
@@ -434,7 +438,7 @@ public:
return static_cast<const T *>(this);
vt = vt->parent;
}
- return 0;
+ return nullptr;
}
template <typename T>
T *as() {
@@ -457,6 +461,7 @@ public:
uint asArrayLength(bool *ok) const;
#endif
+ ReturnedValue *data_ptr() { return &_val; }
ReturnedValue asReturnedValue() const { return _val; }
static Value fromReturnedValue(ReturnedValue val) { Value v; v._val = val; return v; }
@@ -469,7 +474,7 @@ public:
Value &operator=(ReturnedValue v) { _val = v; return *this; }
Value &operator=(Managed *m) {
if (!m) {
- setM(0);
+ setM(nullptr);
} else {
_val = reinterpret_cast<Value *>(m)->_val;
}
@@ -483,7 +488,7 @@ public:
template<typename T>
Value &operator=(const Scoped<T> &t);
};
-V4_ASSERT_IS_TRIVIAL(Value)
+Q_STATIC_ASSERT(std::is_trivial< Value >::value);
inline void Value::mark(MarkStack *markStack)
{
@@ -792,6 +797,94 @@ inline double Value::toInteger() const
}
+template <size_t o>
+struct HeapValue : Value {
+ static Q_CONSTEXPR size_t offset = o;
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
+ void set(EngineBase *e, const Value &newVal) {
+ WriteBarrier::write(e, base(), data_ptr(), newVal.asReturnedValue());
+ }
+ void set(EngineBase *e, Heap::Base *b) {
+ WriteBarrier::write(e, base(), data_ptr(), b->asReturnedValue());
+ }
+};
+
+template <size_t o>
+struct ValueArray {
+ static Q_CONSTEXPR size_t offset = o;
+ uint size;
+ uint alloc;
+ Value values[1];
+
+ Heap::Base *base() {
+ Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
+ Q_ASSERT(base->inUse());
+ return base;
+ }
+
+ void set(EngineBase *e, uint index, Value v) {
+ WriteBarrier::write(e, base(), values[index].data_ptr(), v.asReturnedValue());
+ }
+ void set(EngineBase *e, uint index, Heap::Base *b) {
+ WriteBarrier::write(e, base(), values[index].data_ptr(), b->asReturnedValue());
+ }
+ inline const Value &operator[] (uint index) const {
+ Q_ASSERT(index < alloc);
+ return values[index];
+ }
+ inline const Value *data() const {
+ return values;
+ }
+
+ void insertData(EngineBase *e, uint index, Value v) {
+ for (uint i = size - 1; i > index; --i) {
+ values[i] = values[i - 1];
+ }
+ set(e, index, v);
+ }
+ void removeData(EngineBase *e, uint index, int n = 1) {
+ Q_UNUSED(e);
+ for (uint i = index; i < size - n; ++i) {
+ values[i] = values[i + n];
+ }
+ }
+
+ void mark(MarkStack *markStack) {
+ Value *v = values;
+ const Value *end = v + alloc;
+ if (alloc > 32*1024) {
+ // drain from time to time to avoid overflows in the js stack
+ Heap::Base **currentBase = markStack->top;
+ while (v < end) {
+ v->mark(markStack);
+ ++v;
+ if (markStack->top >= currentBase + 32*1024) {
+ Heap::Base **oldBase = markStack->base;
+ markStack->base = currentBase;
+ markStack->drain();
+ markStack->base = oldBase;
+ }
+ }
+ } else {
+ while (v < end) {
+ v->mark(markStack);
+ ++v;
+ }
+ }
+ }
+};
+
+// It's really important that the offset of values in this structure is
+// constant across all architecture, otherwise JIT cross-compiled code will
+// have wrong offsets between host and target.
+Q_STATIC_ASSERT(offsetof(ValueArray<0>, values) == 8);
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 00be90b3c2..bee17e0390 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -113,17 +113,17 @@ void VariantPrototype::init()
defineDefaultProperty(engine()->id_toString(), method_toString, 0);
}
-ReturnedValue VariantPrototype::method_preserve(const BuiltinFunction *, CallData *callData)
+ReturnedValue VariantPrototype::method_preserve(const FunctionObject *, const Value *thisObject, const Value *, int)
{
- VariantObject *o = callData->thisObject.as<QV4::VariantObject>();
+ const VariantObject *o = thisObject->as<QV4::VariantObject>();
if (o && o->d()->isScarce())
o->d()->addVmePropertyReference();
RETURN_UNDEFINED();
}
-ReturnedValue VariantPrototype::method_destroy(const BuiltinFunction *, CallData *callData)
+ReturnedValue VariantPrototype::method_destroy(const FunctionObject *, const Value *thisObject, const Value *, int)
{
- VariantObject *o = callData->thisObject.as<QV4::VariantObject>();
+ const VariantObject *o = thisObject->as<QV4::VariantObject>();
if (o) {
if (o->d()->isScarce())
o->d()->addVmePropertyReference();
@@ -132,10 +132,10 @@ ReturnedValue VariantPrototype::method_destroy(const BuiltinFunction *, CallData
RETURN_UNDEFINED();
}
-ReturnedValue VariantPrototype::method_toString(const BuiltinFunction *b, CallData *callData)
+ReturnedValue VariantPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
- VariantObject *o = callData->thisObject.as<QV4::VariantObject>();
+ const VariantObject *o = thisObject->as<QV4::VariantObject>();
if (!o)
RETURN_UNDEFINED();
QString result = o->d()->data().toString();
@@ -147,9 +147,9 @@ ReturnedValue VariantPrototype::method_toString(const BuiltinFunction *b, CallDa
return Encode(v4->newString(result));
}
-ReturnedValue VariantPrototype::method_valueOf(const BuiltinFunction *b, CallData *callData)
+ReturnedValue VariantPrototype::method_valueOf(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
- VariantObject *o = callData->thisObject.as<QV4::VariantObject>();
+ const VariantObject *o = thisObject->as<QV4::VariantObject>();
if (o) {
QVariant v = o->d()->data();
switch (v.type()) {
@@ -170,7 +170,7 @@ ReturnedValue VariantPrototype::method_valueOf(const BuiltinFunction *b, CallDat
break;
}
}
- return callData->thisObject.asReturnedValue();
+ return thisObject->asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 07b3310e91..62fa7ff9a8 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -108,10 +108,10 @@ public:
V4_PROTOTYPE(objectPrototype)
void init();
- static ReturnedValue method_preserve(const BuiltinFunction *, CallData *callData);
- static ReturnedValue method_destroy(const BuiltinFunction *, CallData *callData);
- static ReturnedValue method_toString(const BuiltinFunction *, CallData *callData);
- static ReturnedValue method_valueOf(const BuiltinFunction *, CallData *callData);
+ static ReturnedValue method_preserve(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_destroy(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index bc1cb8caa7..bd07473176 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -492,6 +492,7 @@ static bool compareEqualInt(Value &accumulator, Value lhs, int rhs)
if (val.isDouble()) \
d = val.doubleValue(); \
else { \
+ STORE_ACC(); \
d = val.toNumberImpl(); \
CHECK_EXCEPTION; \
} \
@@ -552,17 +553,17 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
QV4::Debugging::Debugger *debugger = engine->debugger();
-
- const uchar *exceptionHandler = 0;
+ const uchar *exceptionHandler = nullptr;
QV4::Value &accumulator = frame.jsFrame->accumulator;
QV4::ReturnedValue acc = Encode::undefined();
#ifdef V4_ENABLE_JIT
- static const bool forceInterpreter = qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER");
- if (function->jittedCode == nullptr) {
- if (ExecutionEngine::canJIT() && debugger == nullptr && !forceInterpreter)
+ if (function->jittedCode == nullptr && debugger == nullptr) {
+ if (engine->canJIT(function))
QV4::JIT::BaselineJIT(function).generate();
+ else
+ ++function->interpreterCallCount;
}
#endif // V4_ENABLE_JIT
@@ -634,7 +635,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
MOTH_BEGIN_INSTR(StoreLocal)
CHECK_EXCEPTION;
auto cc = static_cast<Heap::CallContext *>(stack[CallData::Context].m());
- QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, ACC);
+ QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
MOTH_END_INSTR(StoreLocal)
MOTH_BEGIN_INSTR(LoadScopedLocal)
@@ -645,7 +646,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
MOTH_BEGIN_INSTR(StoreScopedLocal)
CHECK_EXCEPTION;
auto cc = getScope(stack, scope);
- QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, ACC);
+ QV4::WriteBarrier::write(engine, cc, cc->locals.values[index].data_ptr(), acc);
MOTH_END_INSTR(StoreScopedLocal)
MOTH_BEGIN_INSTR(LoadRuntimeString)
@@ -839,6 +840,18 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
CHECK_EXCEPTION;
MOTH_END_INSTR(CallGlobalLookup)
+ MOTH_BEGIN_INSTR(CallScopeObjectProperty)
+ STORE_IP();
+ acc = Runtime::method_callQmlScopeObjectProperty(engine, stack + base, name, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CallScopeObjectProperty)
+
+ MOTH_BEGIN_INSTR(CallContextObjectProperty)
+ STORE_IP();
+ acc = Runtime::method_callQmlContextObjectProperty(engine, stack + base, name, stack + argv, argc);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(CallContextObjectProperty)
+
MOTH_BEGIN_INSTR(SetExceptionHandler)
exceptionHandler = offset ? code + offset : nullptr;
MOTH_END_INSTR(SetExceptionHandler)
@@ -1145,14 +1158,13 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
MOTH_BEGIN_INSTR(CmpInstanceOf)
// 11.8.6, 5: rval must be an Object
- const Object *rhs = Primitive::fromReturnedValue(acc).as<Object>();
- if (Q_UNLIKELY(!rhs)) {
+ if (Q_UNLIKELY(!Primitive::fromReturnedValue(acc).isObject())) {
acc = engine->throwTypeError();
goto catchException;
}
// 11.8.6, 7: call "HasInstance", which we term instanceOf, and return the result.
- acc = rhs->instanceOf(STACK_VALUE(lhs));
+ acc = Primitive::fromReturnedValue(acc).objectValue()->instanceOf(STACK_VALUE(lhs));
CHECK_EXCEPTION;
MOTH_END_INSTR(CmpInstanceOf)
@@ -1294,9 +1306,9 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
MOTH_END_INSTR(BitXor)
MOTH_BEGIN_INSTR(UShr)
- uint l = STACK_VALUE(lhs).toUInt32();
+ VALUE_TO_INT(l, STACK_VALUE(lhs));
VALUE_TO_INT(a, ACC);
- acc = Encode(l >> uint(a & 0x1f));
+ acc = Encode(static_cast<uint>(l) >> uint(a & 0x1f));
MOTH_END_INSTR(UShr)
MOTH_BEGIN_INSTR(Shr)
@@ -1345,12 +1357,12 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
goto functionExit;
MOTH_END_INSTR(Ret)
-#if QT_CONFIG(qml_debug)
MOTH_BEGIN_INSTR(Debug)
+#if QT_CONFIG(qml_debug)
STORE_IP();
debug_slowPath(engine);
- MOTH_END_INSTR(Debug)
#endif // QT_CONFIG(qml_debug)
+ MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(LoadQmlContext)
STACK_VALUE(result) = Runtime::method_loadQmlContext(static_cast<QV4::NoThrowEngine*>(engine));
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index dbf9ed3550..3b7723ca7e 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -53,8 +53,6 @@
#include <private/qv4global_p.h>
-QT_REQUIRE_CONFIG(qml_interpreter);
-
QT_BEGIN_NAMESPACE
namespace QV4 {