diff options
Diffstat (limited to 'src/qml/jsruntime')
28 files changed, 1008 insertions, 604 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index b5b421fa39..b3e607d74a 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -219,7 +219,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V // Item iteration supported, so let's go ahead and try use that. ScopedObject a(createObjectFromCtorOrArray(scope, thatCtor, false, 0)); CHECK_EXCEPTION(); - ScopedObject iterator(scope, Runtime::method_getIterator(scope.engine, itemsObject, true)); + ScopedObject iterator(scope, Runtime::GetIterator::call(scope.engine, itemsObject, true)); CHECK_EXCEPTION(); // symbol_iterator threw; whoops. if (!iterator) { return scope.engine->throwTypeError(); // symbol_iterator wasn't an object. @@ -236,11 +236,11 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V if (k > (static_cast<qint64>(1) << 53) - 1) { ScopedValue falsey(scope, Encode(false)); ScopedValue error(scope, scope.engine->throwTypeError()); - return Runtime::method_iteratorClose(scope.engine, iterator, falsey); + return Runtime::IteratorClose::call(scope.engine, iterator, falsey); } // Retrieve the next value. If the iteration ends, we're done here. - done = Value::fromReturnedValue(Runtime::method_iteratorNext(scope.engine, iterator, nextValue)); + done = Value::fromReturnedValue(Runtime::IteratorNext::call(scope.engine, iterator, nextValue)); CHECK_EXCEPTION(); if (done->toBoolean()) { if (ArrayObject *ao = a->as<ArrayObject>()) { @@ -257,7 +257,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V mapArguments[1] = Value::fromDouble(k); mappedValue = mapfn->call(thisArg, mapArguments, 2); if (scope.engine->hasException) - return Runtime::method_iteratorClose(scope.engine, iterator, Value::fromBoolean(false)); + return Runtime::IteratorClose::call(scope.engine, iterator, Value::fromBoolean(false)); } else { mappedValue = *nextValue; } @@ -271,7 +271,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V if (scope.engine->hasException) { ScopedValue falsey(scope, Encode(false)); - return Runtime::method_iteratorClose(scope.engine, iterator, falsey); + return Runtime::IteratorClose::call(scope.engine, iterator, falsey); } k++; @@ -387,7 +387,7 @@ ReturnedValue ArrayPrototype::method_toLocaleString(const FunctionObject *b, con v = instance->get(k); if (v->isNullOrUndefined()) continue; - v = Runtime::method_callElement(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0); + v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0); s = v->toString(scope.engine); if (scope.hasException()) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 94b1a9fb73..b3bcfe21d5 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -81,17 +81,17 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b return c; } -Heap::CallContext *ExecutionContext::cloneBlockContext(Heap::CallContext *context) +Heap::CallContext *ExecutionContext::cloneBlockContext(ExecutionEngine *engine, + Heap::CallContext *callContext) { - uint nLocals = context->locals.alloc; + uint nLocals = callContext->locals.alloc; size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals; - ExecutionEngine *v4 = context->internalClass->engine; - Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, context->internalClass); - memcpy(c, context, requiredMemory); + Heap::CallContext *c = engine->memoryManager->allocManaged<CallContext>( + requiredMemory, callContext->internalClass); + memcpy(c, callContext, requiredMemory); return c; - } Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame) @@ -128,7 +128,7 @@ Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame) return c; } -Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with) +Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with) const { Heap::ExecutionContext *c = engine()->memoryManager->alloc<ExecutionContext>(Heap::ExecutionContext::Type_WithContext); c->outer.set(engine(), d()); diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 5cd2f9ddf0..75fa2d08e6 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -150,9 +150,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed V4_INTERNALCLASS(ExecutionContext) static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex); - static Heap::CallContext *cloneBlockContext(Heap::CallContext *context); + static Heap::CallContext *cloneBlockContext(ExecutionEngine *engine, + Heap::CallContext *callContext); static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame); - Heap::ExecutionContext *newWithContext(Heap::Object *with); + Heap::ExecutionContext *newWithContext(Heap::Object *with) const; static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName); void createMutableBinding(String *name, bool deletable); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f506e4015e..ab980e99df 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -51,6 +51,9 @@ #include <QDir> #include <QFileInfo> #include <QLoggingCategory> +#if QT_CONFIG(regularexpression) +#include <QRegularExpression> +#endif #ifndef V4_BOOTSTRAP @@ -860,6 +863,13 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re) return memoryManager->allocate<RegExpObject>(re); } +#if QT_CONFIG(regularexpression) +Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re) +{ + return memoryManager->allocate<RegExpObject>(re); +} +#endif + Heap::Object *ExecutionEngine::newErrorObject(const Value &value) { return ErrorObject::create<ErrorObject>(this, value, errorCtor()); @@ -1072,6 +1082,12 @@ extern "C" Q_QML_EXPORT char *qt_v4StackTrace(void *executionContext) return v4StackTrace(reinterpret_cast<const ExecutionContext *>(executionContext)); } +extern "C" Q_QML_EXPORT char *qt_v4StackTraceForEngine(void *executionEngine) +{ + auto engine = (reinterpret_cast<const ExecutionEngine *>(executionEngine)); + return v4StackTrace(engine->currentContext()); +} + QUrl ExecutionEngine::resolvedUrl(const QString &file) { QUrl src(file); @@ -1269,6 +1285,7 @@ static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &va const QByteArray &targetType, void **result); static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst); +static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst); static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap); static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &value) { @@ -1305,7 +1322,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int && !value.as<ArrayObject>() && !value.as<FunctionObject>()) { return QVariant::fromValue(QV4::JsonObject::toJsonObject(object)); } else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) { - return qVariantFromValue<QObject *>(wrapper->object()); + return QVariant::fromValue<QObject *>(wrapper->object()); } else if (object->as<QV4::QQmlContextWrapper>()) { return QVariant(); } else if (QV4::QQmlTypeWrapper *w = object->as<QV4::QQmlTypeWrapper>()) { @@ -1336,7 +1353,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int } } - return qVariantFromValue<QList<QObject*> >(list); + return QVariant::fromValue<QList<QObject*> >(list); } else if (typeHint == QMetaType::QJsonArray) { return QVariant::fromValue(QV4::JsonObject::toJsonArray(a)); } @@ -1379,8 +1396,13 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int QV4::ScopedObject o(scope, value); Q_ASSERT(o); - if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>()) + if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>()) { +#if QT_CONFIG(regularexpression) + if (typeHint != QMetaType::QRegExp) + return re->toQRegularExpression(); +#endif return re->toQRegExp(); + } if (createJSValueForObjects) return QVariant::fromValue(QJSValue(scope.engine, o->asReturnedValue())); @@ -1442,35 +1464,6 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V return result; } -static QV4::ReturnedValue arrayFromVariantList(QV4::ExecutionEngine *e, const QVariantList &list) -{ - QV4::Scope scope(e); - QV4::ScopedArrayObject a(scope, e->newArrayObject()); - int len = list.count(); - a->arrayReserve(len); - QV4::ScopedValue v(scope); - for (int ii = 0; ii < len; ++ii) - a->arrayPut(ii, (v = scope.engine->fromVariant(list.at(ii)))); - - a->setArrayLengthUnchecked(len); - return a.asReturnedValue(); -} - -static QV4::ReturnedValue objectFromVariantMap(QV4::ExecutionEngine *e, const QVariantMap &map) -{ - QV4::Scope scope(e); - QV4::ScopedObject o(scope, e->newObject()); - QV4::ScopedString s(scope); - QV4::ScopedValue v(scope); - for (QVariantMap::const_iterator iter = map.begin(), cend = map.end(); iter != cend; ++iter) { - s = e->newString(iter.key()); - o->put(s, (v = e->fromVariant(iter.value()))); - } - return o.asReturnedValue(); -} - -Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); - QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) { int type = variant.userType(); @@ -1520,6 +1513,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr))); case QMetaType::QRegExp: return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr))); +#if QT_CONFIG(regularexpression) + case QMetaType::QRegularExpression: + return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr))); +#endif case QMetaType::QObjectStar: return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr)); #if QT_CONFIG(qml_sequence_object) @@ -1534,9 +1531,9 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) } #endif case QMetaType::QVariantList: - return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr)); + return variantListToJS(this, *reinterpret_cast<const QVariantList *>(ptr)); case QMetaType::QVariantMap: - return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr)); + return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(ptr)); case QMetaType::QJsonValue: return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr)); case QMetaType::QJsonObject: @@ -1593,6 +1590,11 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) return retn->asReturnedValue(); #endif + if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) { + QSequentialIterable lst = variant.value<QSequentialIterable>(); + return sequentialIterableToJS(this, lst); + } + if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type)) return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type); } @@ -1672,99 +1674,13 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) { Q_ASSERT(data != nullptr); - // check if it's one of the types we know - switch (QMetaType::Type(type)) { - case QMetaType::UnknownType: - case QMetaType::Void: - return QV4::Encode::undefined(); - case QMetaType::Nullptr: - case QMetaType::VoidStar: - return QV4::Encode::null(); - case QMetaType::Bool: - return QV4::Encode(*reinterpret_cast<const bool*>(data)); - case QMetaType::Int: - return QV4::Encode(*reinterpret_cast<const int*>(data)); - case QMetaType::UInt: - return QV4::Encode(*reinterpret_cast<const uint*>(data)); - case QMetaType::LongLong: - return QV4::Encode(double(*reinterpret_cast<const qlonglong*>(data))); - case QMetaType::ULongLong: -#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 -#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") - return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data))); -#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data))); -#else - return QV4::Encode(double(*reinterpret_cast<const qulonglong*>(data))); -#endif - case QMetaType::Double: - return QV4::Encode(*reinterpret_cast<const double*>(data)); - case QMetaType::QString: - return newString(*reinterpret_cast<const QString*>(data))->asReturnedValue(); - case QMetaType::QByteArray: - return newArrayBuffer(*reinterpret_cast<const QByteArray*>(data))->asReturnedValue(); - case QMetaType::Float: - return QV4::Encode(*reinterpret_cast<const float*>(data)); - case QMetaType::Short: - return QV4::Encode((int)*reinterpret_cast<const short*>(data)); - case QMetaType::UShort: - return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(data)); - case QMetaType::Char: - return QV4::Encode((int)*reinterpret_cast<const char*>(data)); - case QMetaType::UChar: - return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(data)); - case QMetaType::QChar: - return QV4::Encode((int)(*reinterpret_cast<const QChar*>(data)).unicode()); - case QMetaType::QStringList: - return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(data))); - case QMetaType::QVariantList: - return variantListToJS(this, *reinterpret_cast<const QVariantList *>(data)); - case QMetaType::QVariantMap: - return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(data)); - case QMetaType::QDateTime: - return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(data))); - case QMetaType::QDate: - return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(data)))); - case QMetaType::QRegExp: - return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(data))); - case QMetaType::QObjectStar: - return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data)); - case QMetaType::QVariant: + QVariant variant(type, data); + if (QMetaType::Type(variant.type()) == QMetaType::QVariant) { + // unwrap it: this is tested in QJSEngine, and makes the most sense for + // end-user code too. return variantToJS(this, *reinterpret_cast<const QVariant*>(data)); - case QMetaType::QJsonValue: - return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(data)); - case QMetaType::QJsonObject: - return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(data)); - case QMetaType::QJsonArray: - return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(data)); - default: - if (type == qMetaTypeId<QJSValue>()) { - return QJSValuePrivate::convertedToValue(this, *reinterpret_cast<const QJSValue*>(data)); - } else { - QByteArray typeName = QMetaType::typeName(type); - if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) { - return QV4::Encode::null(); - } - QMetaType mt(type); - if (auto metaObject = mt.metaObject()) { - auto flags = mt.flags(); - if (flags & QMetaType::IsGadget) { - return QV4::QQmlValueTypeWrapper::create(this, QVariant(type, data), metaObject, type); - } else if (flags & QMetaType::PointerToQObject) { - return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data)); - } - } - if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) { - auto v = QVariant(type, data); - QSequentialIterable lst = v.value<QSequentialIterable>(); - return sequentialIterableToJS(this, lst); - } - // Fall back to wrapping in a QVariant. - return QV4::Encode(newVariantObject(QVariant(type, data))); - } } - Q_UNREACHABLE(); - return 0; + return fromVariant(variant); } ReturnedValue ExecutionEngine::global() @@ -1969,6 +1885,13 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data) *reinterpret_cast<QRegExp *>(data) = r->toQRegExp(); return true; } break; +#if QT_CONFIG(regularexpression) + case QMetaType::QRegularExpression: + if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) { + *reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression(); + return true; + } break; +#endif case QMetaType::QObjectStar: { const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>(); if (qobjectWrapper || value->isNull()) { diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 86367c0ece..6df4545014 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -520,6 +520,9 @@ public: Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags); Heap::RegExpObject *newRegExpObject(RegExp *re); Heap::RegExpObject *newRegExpObject(const QRegExp &re); +#if QT_CONFIG(regularexpression) + Heap::RegExpObject *newRegExpObject(const QRegularExpression &re); +#endif Heap::Object *newErrorObject(const Value &value); Heap::Object *newErrorObject(const QString &message); @@ -631,17 +634,6 @@ private: QScopedPointer<QV4::Promise::ReactionHandler> m_reactionHandler; }; -// This is a trick to tell the code generators that functions taking a NoThrowContext won't -// throw exceptions and therefore don't need a check after the call. -#ifndef V4_BOOTSTRAP -struct NoThrowEngine : public ExecutionEngine -{ -}; -#else -struct NoThrowEngine; -#endif - - #define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \ ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 54bce7d7b3..c2c3fa0474 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -473,11 +473,11 @@ bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, return false; } - if (l->setter == Lookup::setter0 || l->setter == Lookup::setter0Inline) { + if (l->setter == Lookup::setter0MemberData || l->setter == Lookup::setter0Inline) { l->objectLookupTwoClasses.ic = first.objectLookup.ic; l->objectLookupTwoClasses.ic2 = second.objectLookup.ic; - l->objectLookupTwoClasses.offset = first.objectLookup.offset; - l->objectLookupTwoClasses.offset2 = second.objectLookup.offset; + l->objectLookupTwoClasses.offset = first.objectLookup.index; + l->objectLookupTwoClasses.offset2 = second.objectLookup.index; l->setter = setter0setter0; return true; } @@ -498,11 +498,11 @@ bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c return o->put(name, value); } -bool Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) +bool Lookup::setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { Heap::Object *o = static_cast<Heap::Object *>(object.heapObject()); if (o && o->internalClass == l->objectLookup.ic) { - o->setProperty(engine, l->objectLookup.offset, value); + o->memberData->values.set(engine, l->objectLookup.offset, value); return true; } @@ -513,7 +513,7 @@ bool Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, co { Heap::Object *o = static_cast<Heap::Object *>(object.heapObject()); if (o && o->internalClass == l->objectLookup.ic) { - o->setInlineProperty(engine, l->objectLookup.offset, value); + o->setInlinePropertyWithOffset(engine, l->objectLookup.offset, value); return true; } diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 03dc5f6d3c..7309749a81 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -81,8 +81,9 @@ struct Lookup { } markDef; struct { Heap::InternalClass *ic; - quintptr _unused; - int offset; + quintptr unused; + uint index; + uint offset; } objectLookup; struct { quintptr protoId; @@ -92,8 +93,8 @@ struct Lookup { struct { Heap::InternalClass *ic; Heap::InternalClass *ic2; - int offset; - int offset2; + uint offset; + uint offset2; } objectLookupTwoClasses; struct { quintptr protoId; @@ -111,12 +112,14 @@ struct Lookup { struct { Heap::InternalClass *newClass; quintptr protoId; - int offset; + uint offset; + uint unused; } insertionLookup; struct { quintptr _unused; quintptr _unused2; uint index; + uint unused; } indexedLookup; struct { Heap::InternalClass *ic; @@ -187,7 +190,7 @@ struct Lookup { static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); Q_NEVER_INLINE static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); - static bool setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static bool setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); diff --git a/src/qml/jsruntime/qv4mapobject.cpp b/src/qml/jsruntime/qv4mapobject.cpp index 68741e7677..90e1908a84 100644 --- a/src/qml/jsruntime/qv4mapobject.cpp +++ b/src/qml/jsruntime/qv4mapobject.cpp @@ -80,7 +80,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, if (!adder) return scope.engine->throwTypeError(); - ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true)); + ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true)); if (scope.hasException()) return Encode::undefined(); Q_ASSERT(iter); @@ -89,7 +89,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, Value *arguments = scope.alloc(2); ScopedValue done(scope); forever { - done = Runtime::method_iteratorNext(scope.engine, iter, obj); + done = Runtime::IteratorNext::call(scope.engine, iter, obj); if (scope.hasException()) break; if (done->toBoolean()) @@ -112,7 +112,7 @@ ReturnedValue WeakMapCtor::construct(const FunctionObject *f, const Value *argv, break; } ScopedValue falsey(scope, Encode(false)); - return Runtime::method_iteratorClose(scope.engine, iter, falsey); + return Runtime::IteratorClose::call(scope.engine, iter, falsey); } } return a->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 7dd0a247d6..efab9a6454 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -786,8 +786,15 @@ bool Object::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, return lookup->setter(lookup, engine, *object, value); } else if (idx.attrs.isData() && idx.attrs.isWritable()) { lookup->objectLookup.ic = object->internalClass(); - lookup->objectLookup.offset = idx.index; - lookup->setter = idx.index < object->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0; + lookup->objectLookup.index = idx.index; + const auto nInline = object->d()->vtable()->nInlineProperties; + if (idx.index < nInline) { + lookup->setter = Lookup::setter0Inline; + lookup->objectLookup.offset = idx.index + object->d()->vtable()->inlinePropertyOffset; + } else { + lookup->setter = Lookup::setter0MemberData; + lookup->objectLookup.offset = idx.index - nInline; + } return lookup->setter(lookup, engine, *object, value); } else { // ### handle setter diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index c3f1cb2c35..567382cbc0 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -79,21 +79,21 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) { } const Value *inlinePropertyDataWithOffset(uint indexWithOffset) const { - Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < vtable()->inlinePropertyOffset + vtable()->nInlineProperties); + Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties)); return reinterpret_cast<const Value *>(this) + indexWithOffset; } const Value *inlinePropertyData(uint index) const { Q_ASSERT(index < vtable()->nInlineProperties); return reinterpret_cast<const Value *>(this) + vtable()->inlinePropertyOffset + index; } - void setInlineProperty(ExecutionEngine *e, uint index, Value v) { - Q_ASSERT(index < vtable()->nInlineProperties); - Value *prop = reinterpret_cast<Value *>(this) + vtable()->inlinePropertyOffset + index; + void setInlinePropertyWithOffset(ExecutionEngine *e, uint indexWithOffset, Value v) { + Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties)); + Value *prop = reinterpret_cast<Value *>(this) + indexWithOffset; 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; + void setInlinePropertyWithOffset(ExecutionEngine *e, uint indexWithOffset, Heap::Base *b) { + Q_ASSERT(indexWithOffset >= vtable()->inlinePropertyOffset && indexWithOffset < uint(vtable()->inlinePropertyOffset + vtable()->nInlineProperties)); + Value *prop = reinterpret_cast<Value *>(this) + indexWithOffset; WriteBarrier::write(e, this, prop->data_ptr(), Value::fromHeapObject(b).asReturnedValue()); } @@ -115,7 +115,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) { void setProperty(ExecutionEngine *e, uint index, Value v) { uint nInline = vtable()->nInlineProperties; if (index < nInline) { - setInlineProperty(e, index, v); + setInlinePropertyWithOffset(e, index + vtable()->inlinePropertyOffset, v); return; } index -= nInline; @@ -124,7 +124,7 @@ DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) { void setProperty(ExecutionEngine *e, uint index, Heap::Base *b) { uint nInline = vtable()->nInlineProperties; if (index < nInline) { - setInlineProperty(e, index, b); + setInlinePropertyWithOffset(e, index + vtable()->inlinePropertyOffset, b); return; } index -= nInline; diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp index 8450655334..b32e227b58 100644 --- a/src/qml/jsruntime/qv4promiseobject.cpp +++ b/src/qml/jsruntime/qv4promiseobject.cpp @@ -496,7 +496,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this ScopedFunctionObject reject(scope, capability->d()->reject); ScopedObject itemsObject(scope, argv); - ScopedObject iteratorObject(scope, Runtime::method_getIterator(e, itemsObject, true)); + ScopedObject iteratorObject(scope, Runtime::GetIterator::call(e, itemsObject, true)); if (!iteratorObject || scope.hasException()) { ScopedObject error(scope); if (scope.hasException()) { @@ -521,7 +521,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this for (;;) { Scope scope(e); ScopedValue nextValue(scope); - doneValue = Value::fromReturnedValue(Runtime::method_iteratorNext(e, iteratorObject, nextValue)); + doneValue = Value::fromReturnedValue(Runtime::IteratorNext::call(e, iteratorObject, nextValue)); if (doneValue->toBoolean()) break; @@ -549,7 +549,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this } if (!doneValue->toBoolean()) - completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue); + completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue); reject->call(newPromise, completion, 1); return newPromise.asReturnedValue(); @@ -557,7 +557,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1))); if (!nextPromise || scope.hasException()) { - ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue)); + ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); dropException(e); @@ -579,7 +579,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this } if (!doneValue->toBoolean()) - completion = Runtime::method_iteratorClose(scope.engine, iteratorObject, doneValue); + completion = Runtime::IteratorClose::call(scope.engine, iteratorObject, doneValue); reject->call(newPromise, completion, 1); return newPromise.asReturnedValue(); @@ -598,7 +598,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this dropException(e); if (!doneValue->toBoolean()) - completion = Runtime::method_iteratorClose(scope.engine, iteratorObject, doneValue); + completion = Runtime::IteratorClose::call(scope.engine, iteratorObject, doneValue); reject->call(newPromise, completion, 1); return newPromise.asReturnedValue(); @@ -646,7 +646,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi ScopedFunctionObject reject(scope, capability->d()->reject); ScopedObject itemsObject(scope, argv); - ScopedObject iteratorObject(scope, Runtime::method_getIterator(e, itemsObject, true)); + ScopedObject iteratorObject(scope, Runtime::GetIterator::call(e, itemsObject, true)); if (!iteratorObject) { ScopedObject error(scope, e->newTypeErrorObject(QStringLiteral("Type error"))); reject->call(newPromise, error, 1); @@ -657,10 +657,10 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi for (;;) { Scope scope(e); ScopedValue nextValue(scope); - doneValue = Value::fromReturnedValue(Runtime::method_iteratorNext(e, iteratorObject, nextValue)); + doneValue = Value::fromReturnedValue(Runtime::IteratorNext::call(e, iteratorObject, nextValue)); if (scope.hasException()) { - ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue)); + ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); dropException(e); @@ -695,7 +695,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi } if (!doneValue->toBoolean()) - completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue); + completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue); reject->call(newPromise, completion, 1); return newPromise.asReturnedValue(); @@ -703,7 +703,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1))); if (!nextPromise || scope.hasException()) { - ScopedValue completion(scope, Runtime::method_iteratorClose(e, iteratorObject, doneValue)); + ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); dropException(e); @@ -723,7 +723,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi } if (!doneValue->toBoolean()) - completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue); + completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue); reject->call(newPromise, completion, 1); return newPromise.asReturnedValue(); @@ -742,7 +742,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi dropException(e); if (!doneValue->toBoolean()) - completion = Runtime::method_iteratorClose(e, iteratorObject, doneValue); + completion = Runtime::IteratorClose::call(e, iteratorObject, doneValue); reject->call(newPromise, completion, 1); return newPromise.asReturnedValue(); diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 12ada7ee70..d2aa334805 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qv4qmlcontext_p.h" -#include <private/qv8engine_p.h> #include <private/qqmlengine_p.h> #include <private/qqmlcontext_p.h> diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 377c30617a..d85e8c94eb 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -39,7 +39,7 @@ #include "qv4qobjectwrapper_p.h" -#include <private/qqmlpropertycache_p.h> +#include <private/qqmlstaticmetaobject_p.h> #include <private/qqmlengine_p.h> #include <private/qqmlvmemetaobject_p.h> #include <private/qqmlbinding_p.h> @@ -1384,6 +1384,9 @@ static int MatchScore(const QV4::Value &actual, int conversionType) } else if (actual.as<QV4::RegExpObject>()) { switch (conversionType) { case QMetaType::QRegExp: +#if QT_CONFIG(regularexpression) + case QMetaType::QRegularExpression: +#endif return 0; default: return 10; diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 2558ede401..795bf241f2 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -55,9 +55,7 @@ #include <QtCore/qmetatype.h> #include <QtCore/qpair.h> #include <QtCore/qhash.h> -#include <private/qhashedstring_p.h> #include <private/qqmldata_p.h> -#include <private/qqmlpropertycache_p.h> #include <private/qintrusivelist_p.h> #include <private/qv4value_p.h> diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp index 15dcb602eb..0772770d63 100644 --- a/src/qml/jsruntime/qv4reflect.cpp +++ b/src/qml/jsruntime/qv4reflect.cpp @@ -148,7 +148,7 @@ ReturnedValue Reflect::method_deleteProperty(const FunctionObject *f, const Valu if (!argc || !argv[0].isObject()) return e->throwTypeError(); - bool result = Runtime::method_deleteProperty(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue()); + bool result = Runtime::DeleteProperty_NoThrow::call(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue()); return Encode(result); } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 39a2e96b45..5bd25dcbec 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -50,6 +50,9 @@ #include <QtCore/QDebug> #include <QtCore/qregexp.h> +#if QT_CONFIG(regularexpression) +#include <QtCore/qregularexpression.h> +#endif #include <cassert> #include <typeinfo> #include <iostream> @@ -134,6 +137,25 @@ void Heap::RegExpObject::init(const QRegExp &re) o->initProperties(); } +#if QT_CONFIG(regularexpression) +// Converts a QRegularExpression to a JS RegExp. +// The conversion is not 100% exact since ECMA regexp and QRegularExpression +// have different semantics/flags, but we try to do our best. +void Heap::RegExpObject::init(const QRegularExpression &re) +{ + Object::init(); + + Scope scope(internalClass->engine); + Scoped<QV4::RegExpObject> o(scope, this); + + const uint flags = (re.patternOptions() & QRegularExpression::CaseInsensitiveOption) + ? CompiledData::RegExp::RegExp_IgnoreCase + : CompiledData::RegExp::RegExp_NoFlags; + o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, re.pattern(), flags)); + o->initProperties(); +} +#endif + void RegExpObject::initProperties() { setProperty(Index_LastIndex, Value::fromInt32(0)); @@ -150,6 +172,20 @@ QRegExp RegExpObject::toQRegExp() const return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2); } +#if QT_CONFIG(regularexpression) +// Converts a JS RegExp to a QRegularExpression. +// The conversion is not 100% exact since ECMA regexp and QRegularExpression +// have different semantics/flags, but we try to do our best. +QRegularExpression RegExpObject::toQRegularExpression() const +{ + QRegularExpression::PatternOptions caseSensitivity + = (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase) + ? QRegularExpression::CaseInsensitiveOption + : QRegularExpression::NoPatternOption; + return QRegularExpression(*value()->pattern, caseSensitivity); +} +#endif + QString RegExpObject::toString() const { QString p = *value()->pattern; diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index a584404c0b..04b533e49d 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -81,6 +81,9 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) { void init(); void init(QV4::RegExp *value); void init(const QRegExp &re); +#if QT_CONFIG(regularexpression) + void init(const QRegularExpression &re); +#endif }; #define RegExpCtorMembers(class, Member) \ @@ -138,6 +141,9 @@ struct RegExpObject: Object { } QRegExp toQRegExp() const; +#if QT_CONFIG(regularexpression) + QRegularExpression toQRegularExpression() const; +#endif QString toString() const; QString source() const; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index f7c339dc26..8f2b162106 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -63,7 +63,6 @@ #include "qv4qobjectwrapper_p.h" #include "qv4symbol_p.h" #include "qv4generatorobject_p.h" -#include <private/qv8engine_p.h> #endif #include <QtCore/QDebug> @@ -225,13 +224,6 @@ void RuntimeCounters::count(const char *func, uint tag1, uint tag2) #ifndef V4_BOOTSTRAP -Runtime::Runtime() -{ -#define INIT_METHOD(returnvalue, name, args) runtimeMethods[name] = reinterpret_cast<void*>(&method_##name); -FOR_EACH_RUNTIME_METHOD(INIT_METHOD) -#undef INIT_METHOD -} - void RuntimeHelpers::numberToString(QString *result, double num, int radix) { Q_ASSERT(result); @@ -320,7 +312,7 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) result->prepend(QLatin1Char('-')); } -ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId) +ReturnedValue Runtime::Closure::call(ExecutionEngine *engine, int functionId) { QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId]; Q_ASSERT(clos); @@ -330,7 +322,7 @@ ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId) return FunctionObject::createScriptFunction(current, clos)->asReturnedValue(); } -bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base, const Value &index) +Bool Runtime::DeleteProperty_NoThrow::call(ExecutionEngine *engine, const Value &base, const Value &index) { Scope scope(engine); ScopedObject o(scope, base.toObject(engine)); @@ -344,14 +336,36 @@ bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base, return o->deleteProperty(key); } -bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex) +ReturnedValue Runtime::DeleteProperty::call(ExecutionEngine *engine, QV4::Function *function, const QV4::Value &base, const QV4::Value &index) +{ + if (!Runtime::DeleteProperty_NoThrow::call(engine, base, index)) { + if (function->isStrict()) + engine->throwTypeError(); + return Encode(false); + } else { + return Encode(true); + } +} + +Bool Runtime::DeleteName_NoThrow::call(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).deleteProperty(name); } -QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &lval, const Value &rval) +ReturnedValue Runtime::DeleteName::call(ExecutionEngine *engine, Function *function, int name) +{ + if (!Runtime::DeleteName_NoThrow::call(engine, name)) { + if (function->isStrict()) + engine->throwTypeError(); + return Encode(false); + } else { + return Encode(true); + } +} + +QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Value &lval, const Value &rval) { // 11.8.6, 5: rval must be an Object const Object *rhs = rval.as<Object>(); @@ -376,7 +390,7 @@ QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Val return Encode(result->toBoolean()); } -QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right) { Object *ro = right.objectValue(); if (!ro) @@ -604,13 +618,12 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu return Encode(x + y); } -ReturnedValue RuntimeHelpers::getTemplateObject(Function *function, int index) +ReturnedValue Runtime::GetTemplateObject::call(Function *function, int index) { return function->compilationUnit->templateObjectAt(index)->asReturnedValue(); } - -void Runtime::method_storeProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) +void Runtime::StoreProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) { Scope scope(engine); QV4::Function *v4Function = engine->currentStackFrame->v4Function; @@ -683,7 +696,7 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine, return o->get(name); } -ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index) +ReturnedValue Runtime::LoadElement::call(ExecutionEngine *engine, const Value &object, const Value &index) { if (index.isPositiveInt()) { uint idx = static_cast<uint>(index.int_32()); @@ -704,7 +717,7 @@ ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value & return getElementFallback(engine, object, index); } -ReturnedValue Runtime::method_loadElement_traced(ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot) +ReturnedValue Runtime::LoadElement_Traced::call(ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot) { *traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed); if (index.isPositiveInt()) { @@ -761,7 +774,7 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val return o->put(name, value); } -void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) +void Runtime::StoreElement::call(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) { if (index.isPositiveInt()) { uint idx = static_cast<uint>(index.int_32()); @@ -783,7 +796,7 @@ void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, engine->throwTypeError(); } -void Runtime::method_storeElement_traced(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot) +void Runtime::StoreElement_traced::call(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot) { *traceSlot |= quint8(ObservedTraceValues::ArrayWasAccessed); if (index.isPositiveInt()) { @@ -807,7 +820,7 @@ void Runtime::method_storeElement_traced(ExecutionEngine *engine, const Value &o engine->throwTypeError(); } -ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &in, int iterator) +ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &in, int iterator) { Scope scope(engine); ScopedObject o(scope, (Object *)nullptr); @@ -830,7 +843,7 @@ ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value & return engine->newForInIteratorObject(o)->asReturnedValue(); } -ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value &iterator, Value *value) +ReturnedValue Runtime::IteratorNext::call(ExecutionEngine *engine, const Value &iterator, Value *value) { // if we throw an exception from here, return true, not undefined. This is to ensure iteratorDone is set to true // and the stack unwinding won't close the iterator @@ -866,7 +879,7 @@ ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value return Encode(false); } -ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object) +ReturnedValue Runtime::IteratorNextForYieldStar::call(ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object) { // the return value encodes how to continue the yield* iteration. // true implies iteration is done, false for iteration to continue @@ -903,7 +916,7 @@ ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine, if (t->isUndefined()) { // no throw method on the iterator ScopedValue done(scope, Encode(false)); - method_iteratorClose(engine, iterator, done); + IteratorClose::call(engine, iterator, done); if (engine->hasException) return Encode::undefined(); return engine->throwTypeError(); @@ -938,7 +951,7 @@ ReturnedValue Runtime::method_iteratorNextForYieldStar(ExecutionEngine *engine, return Encode(false); } -ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value &iterator, const Value &done) +ReturnedValue Runtime::IteratorClose::call(ExecutionEngine *engine, const Value &iterator, const Value &done) { Q_ASSERT(iterator.isObject()); Q_ASSERT(done.isBoolean()); @@ -978,7 +991,7 @@ ReturnedValue Runtime::method_iteratorClose(ExecutionEngine *engine, const Value return originalCompletion(); } -ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, const Value &iterator) +ReturnedValue Runtime::DestructureRestElement::call(ExecutionEngine *engine, const Value &iterator) { Q_ASSERT(iterator.isObject()); @@ -988,7 +1001,7 @@ ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, co uint index = 0; while (1) { ScopedValue n(scope); - ScopedValue done(scope, method_iteratorNext(engine, iterator, n)); + ScopedValue done(scope, IteratorNext::call(engine, iterator, n)); if (engine->hasException) return Encode::undefined(); Q_ASSERT(done->isBoolean()); @@ -1000,7 +1013,7 @@ ReturnedValue Runtime::method_destructureRestElement(ExecutionEngine *engine, co return array->asReturnedValue(); } -void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, const Value &value) +void Runtime::StoreNameSloppy::call(ExecutionEngine *engine, int nameIndex, const Value &value) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); @@ -1010,7 +1023,7 @@ void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, con engine->globalObject->put(name, value); } -void Runtime::method_storeNameStrict(ExecutionEngine *engine, int nameIndex, const Value &value) +void Runtime::StoreNameStrict::call(ExecutionEngine *engine, int nameIndex, const Value &value) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); @@ -1021,7 +1034,7 @@ void Runtime::method_storeNameStrict(ExecutionEngine *engine, int nameIndex, con engine->throwReferenceError(name); } -ReturnedValue Runtime::method_loadProperty(ExecutionEngine *engine, const Value &object, int nameIndex) +ReturnedValue Runtime::LoadProperty::call(ExecutionEngine *engine, const Value &object, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); @@ -1041,7 +1054,7 @@ ReturnedValue Runtime::method_loadProperty(ExecutionEngine *engine, const Value return o->get(name); } -ReturnedValue Runtime::method_loadName(ExecutionEngine *engine, int nameIndex) +ReturnedValue Runtime::LoadName::call(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); @@ -1084,7 +1097,7 @@ static Object *getSuperBase(Scope &scope) return proto; } -ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const Value &property) +ReturnedValue Runtime::LoadSuperProperty::call(ExecutionEngine *engine, const Value &property) { Scope scope(engine); Object *base = getSuperBase(scope); @@ -1096,7 +1109,7 @@ ReturnedValue Runtime::method_loadSuperProperty(ExecutionEngine *engine, const V return base->get(key, &engine->currentStackFrame->jsFrame->thisObject); } -void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &property, const Value &value) +void Runtime::StoreSuperProperty::call(ExecutionEngine *engine, const Value &property, const Value &value) { Scope scope(engine); Object *base = getSuperBase(scope); @@ -1110,7 +1123,40 @@ void Runtime::method_storeSuperProperty(ExecutionEngine *engine, const Value &pr engine->throwTypeError(); } -ReturnedValue Runtime::method_loadSuperConstructor(ExecutionEngine *engine, const Value &t) +ReturnedValue Runtime::LoadGlobalLookup::call(ExecutionEngine *engine, Function *f, int index) +{ + Lookup *l = f->compilationUnit->runtimeLookups + index; + return l->globalGetter(l, engine); +} + +ReturnedValue Runtime::LoadQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index) +{ + Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; + return l->qmlContextPropertyGetter(l, engine, nullptr); +} + +ReturnedValue Runtime::GetLookup::call(ExecutionEngine *engine, Function *f, const Value &base, int index) +{ + Lookup *l = f->compilationUnit->runtimeLookups + index; + return l->getter(l, engine, base); +} + +void Runtime::SetLookupSloppy::call(Function *f, const Value &base, int index, const Value &value) +{ + ExecutionEngine *engine = f->internalClass->engine; + QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + l->setter(l, engine, const_cast<Value &>(base), value); +} + +void Runtime::SetLookupStrict::call(Function *f, const Value &base, int index, const Value &value) +{ + ExecutionEngine *engine = f->internalClass->engine; + QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + if (!l->setter(l, engine, const_cast<Value &>(base), value)) + engine->throwTypeError(); +} + +ReturnedValue Runtime::LoadSuperConstructor::call(ExecutionEngine *engine, const Value &t) { if (engine->currentStackFrame->thisObject() != Value::emptyValue().asReturnedValue()) { return engine->throwReferenceError(QStringLiteral("super() already called."), QString(), 0, 0); // ### fix line number @@ -1143,9 +1189,9 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y) double dx = RuntimeHelpers::toNumber(x); return dx == y.asDouble(); } else if (x.isBoolean()) { - return Runtime::method_compareEqual(Value::fromDouble((double) x.booleanValue()), y); + return Runtime::CompareEqual::call(Value::fromDouble((double) x.booleanValue()), y); } else if (y.isBoolean()) { - return Runtime::method_compareEqual(x, Value::fromDouble((double) y.booleanValue())); + return Runtime::CompareEqual::call(x, Value::fromDouble((double) y.booleanValue())); } else { #ifdef V4_BOOTSTRAP Q_UNIMPLEMENTED(); @@ -1155,11 +1201,11 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y) if (yo && (x.isNumber() || x.isString())) { Scope scope(yo->engine()); ScopedValue py(scope, RuntimeHelpers::objectDefaultValue(yo, PREFERREDTYPE_HINT)); - return Runtime::method_compareEqual(x, py); + return Runtime::CompareEqual::call(x, py); } else if (xo && (y.isNumber() || y.isString())) { Scope scope(xo->engine()); ScopedValue px(scope, RuntimeHelpers::objectDefaultValue(xo, PREFERREDTYPE_HINT)); - return Runtime::method_compareEqual(px, y); + return Runtime::CompareEqual::call(px, y); } #endif } @@ -1182,7 +1228,7 @@ Bool RuntimeHelpers::strictEqual(const Value &x, const Value &y) return false; } -QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r) +QV4::Bool Runtime::CompareGreaterThan::call(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -1210,7 +1256,7 @@ QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue()); QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue()); - return Runtime::method_compareGreaterThan(pl, pr); + return Runtime::CompareGreaterThan::call(pl, pr); #endif } @@ -1219,7 +1265,7 @@ QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r) return dl > dr; } -QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r) +QV4::Bool Runtime::CompareLessThan::call(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -1247,7 +1293,7 @@ QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue()); QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue()); - return Runtime::method_compareLessThan(pl, pr); + return Runtime::CompareLessThan::call(pl, pr); #endif } @@ -1256,7 +1302,7 @@ QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r) return dl < dr; } -QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r) +QV4::Bool Runtime::CompareGreaterEqual::call(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -1284,7 +1330,7 @@ QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue()); QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue()); - return Runtime::method_compareGreaterEqual(pl, pr); + return Runtime::CompareGreaterEqual::call(pl, pr); #endif } @@ -1293,7 +1339,7 @@ QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r) return dl >= dr; } -QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r) +QV4::Bool Runtime::CompareLessEqual::call(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -1321,7 +1367,7 @@ QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, lo ? RuntimeHelpers::objectDefaultValue(lo, QV4::NUMBER_HINT) : l.asReturnedValue()); QV4::ScopedValue pr(scope, ro ? RuntimeHelpers::objectDefaultValue(ro, QV4::NUMBER_HINT) : r.asReturnedValue()); - return Runtime::method_compareLessEqual(pl, pr); + return Runtime::CompareLessEqual::call(pl, pr); #endif } @@ -1331,21 +1377,21 @@ QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r) } #ifndef V4_BOOTSTRAP -Bool Runtime::method_compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right) +Bool Runtime::CompareInstanceof::call(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); Scope scope(engine); - ScopedValue v(scope, method_instanceof(engine, left, right)); + ScopedValue v(scope, Instanceof::call(engine, left, right)); return v->booleanValue(); } -uint Runtime::method_compareIn(ExecutionEngine *engine, const Value &left, const Value &right) +uint Runtime::CompareIn::call(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); Scope scope(engine); - ScopedValue v(scope, method_in(engine, left, right)); + ScopedValue v(scope, In::call(engine, left, right)); return v->booleanValue(); } @@ -1359,7 +1405,7 @@ static ReturnedValue throwPropertyIsNotAFunctionTypeError(ExecutionEngine *engin return engine->throwTypeError(msg); } -ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, Value *argv, int argc) +ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint index, Value argv[], int argc) { Scope scope(engine); Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; @@ -1372,7 +1418,8 @@ ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint ind return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc); } -ReturnedValue Runtime::method_callQmlContextPropertyLookup(ExecutionEngine *engine, uint index, Value *argv, int argc) +ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index, + Value *argv, int argc) { Scope scope(engine); ScopedValue thisObject(scope); @@ -1385,7 +1432,7 @@ ReturnedValue Runtime::method_callQmlContextPropertyLookup(ExecutionEngine *engi return static_cast<FunctionObject &>(function).call(thisObject, argv, argc); } -ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Value *argv, int argc) +ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Value *argv, int argc) { Scope scope(engine); ScopedValue thisObject(scope); @@ -1404,7 +1451,7 @@ ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Va return function->call(thisObject, argv, argc); } -ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, Value *argv, int argc) +ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Value *argv, int argc) { Scope scope(engine); ScopedValue thisObject(scope); @@ -1422,8 +1469,9 @@ ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, V return f->call(thisObject, argv, argc); } -ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc) +ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &baseRef, int nameIndex, Value *argv, int argc) { + const Value *base = &baseRef; Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedObject lookupObject(scope, base); @@ -1437,7 +1485,7 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, } if (base->isManaged()) { - Managed *m = static_cast<Managed *>(base); + const Managed *m = static_cast<const Managed *>(base); lookupObject = m->internalClass()->prototype; Q_ASSERT(m->internalClass()->prototype); } else { @@ -1461,20 +1509,21 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, return f->call(base, argv, argc); } -ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc) +ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc) { Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; // ok to have the value on the stack here - Value f = Value::fromReturnedValue(l->getter(l, engine, *base)); + Value f = Value::fromReturnedValue(l->getter(l, engine, base)); if (!f.isFunctionObject()) return engine->throwTypeError(); - return static_cast<FunctionObject &>(f).call(base, argv, argc); + return static_cast<FunctionObject &>(f).call(&base, argv, argc); } -ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc) +ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &baseRef, const Value &index, Value *argv, int argc) { + const Value *base = &baseRef; Scope scope(engine); ScopedValue thisObject(scope, base->toObject(engine)); base = thisObject; @@ -1483,14 +1532,14 @@ ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, if (engine->hasException) return Encode::undefined(); - ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str)); + ScopedFunctionObject f(scope, static_cast<const Object *>(base)->get(str)); if (!f) return engine->throwTypeError(); return f->call(base, argv, argc); } -ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, Value *argv, int argc) +ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc) { if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); @@ -1498,11 +1547,12 @@ ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &fu return static_cast<const FunctionObject &>(func).call(&undef, argv, argc); } -ReturnedValue Runtime::method_callWithReceiver(ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc) +ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Value &func, + const Value &thisObject, Value argv[], int argc) { if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); - return static_cast<const FunctionObject &>(func).call(thisObject, argv, argc); + return static_cast<const FunctionObject &>(func).call(&thisObject, argv, argc); } struct CallArgs { @@ -1528,11 +1578,11 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc) } // spread element ++i; - it = Runtime::method_getIterator(scope.engine, argv[i], /* ForInIterator */ 1); + it = Runtime::GetIterator::call(scope.engine, argv[i], /* ForInIterator */ 1); if (scope.engine->hasException) return { nullptr, 0 }; while (1) { - done = Runtime::method_iteratorNext(scope.engine, it, v); + done = Runtime::IteratorNext::call(scope.engine, it, v); if (scope.engine->hasException) return { nullptr, 0 }; Q_ASSERT(done->isBoolean()); @@ -1545,7 +1595,7 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc) return { arguments, argCount }; } -ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc) +ReturnedValue Runtime::CallWithSpread::call(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc) { Q_ASSERT(argc >= 1); if (!function.isFunctionObject()) @@ -1559,7 +1609,7 @@ ReturnedValue Runtime::method_callWithSpread(ExecutionEngine *engine, const Valu return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc); } -ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc) +ReturnedValue Runtime::Construct::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc) { if (!function.isFunctionObject()) return engine->throwTypeError(); @@ -1567,7 +1617,7 @@ ReturnedValue Runtime::method_construct(ExecutionEngine *engine, const Value &fu return static_cast<const FunctionObject &>(function).callAsConstructor(argv, argc, &newTarget); } -ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc) +ReturnedValue Runtime::ConstructWithSpread::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc) { if (!function.isFunctionObject()) return engine->throwTypeError(); @@ -1580,7 +1630,7 @@ ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget); } -ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *engine) +ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *engine) { // IMPORTANT! The JIT assumes that this method has the same amount (or less) arguments than // the jitted function, so it can safely do a tail call. @@ -1610,13 +1660,13 @@ ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *en return Encode::undefined(); } -void Runtime::method_throwException(ExecutionEngine *engine, const Value &value) +void Runtime::ThrowException::call(ExecutionEngine *engine, const Value &value) { if (!value.isEmpty()) engine->throwError(value); } -ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &value) +ReturnedValue Runtime::TypeofValue::call(ExecutionEngine *engine, const Value &value) { Scope scope(engine); ScopedString res(scope); @@ -1647,83 +1697,109 @@ ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value & return res.asReturnedValue(); } -QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameIndex) +QV4::ReturnedValue Runtime::TypeofName::call(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); ScopedValue prop(scope, static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name)); // typeof doesn't throw. clear any possible exception scope.engine->hasException = false; - return method_typeofValue(engine, prop); + return TypeofValue::call(engine, prop); } -ReturnedValue Runtime::method_createWithContext(ExecutionEngine *engine, Value *jsStackFrame) +void Runtime::PushCallContext::call(CppStackFrame *frame) { - QV4::Value &accumulator = jsStackFrame[CallData::Accumulator]; - accumulator = accumulator.toObject(engine); - if (engine->hasException) - return Encode::undefined(); - Q_ASSERT(accumulator.isObject()); - const Object &obj = static_cast<const Object &>(accumulator); - ExecutionContext *context = static_cast<ExecutionContext *>(jsStackFrame + CallData::Context); - return context->newWithContext(obj.d())->asReturnedValue(); + frame->jsFrame->context = ExecutionContext::newCallContext(frame)->asReturnedValue(); } -ReturnedValue Runtime::method_createCatchContext(ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex) +ReturnedValue Runtime::PushWithContext::call(ExecutionEngine *engine, const Value &acc) { - ExecutionEngine *e = parent->engine(); - return parent->newCatchContext(e->currentStackFrame, blockIndex, - e->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex])->asReturnedValue(); + CallData *jsFrame = engine->currentStackFrame->jsFrame; + Value &newAcc = jsFrame->accumulator; + newAcc = Value::fromHeapObject(acc.toObject(engine)); + if (!engine->hasException) { + Q_ASSERT(newAcc.isObject()); + const Object &obj = static_cast<const Object &>(newAcc); + Value &context = jsFrame->context; + auto ec = static_cast<const ExecutionContext *>(&context); + context = ec->newWithContext(obj.d())->asReturnedValue(); + } + return newAcc.asReturnedValue(); } -ReturnedValue Runtime::method_createBlockContext(ExecutionContext *parent, int index) +void Runtime::PushCatchContext::call(ExecutionEngine *engine, int blockIndex, int exceptionVarNameIndex) { - ExecutionEngine *e = parent->engine(); - return parent->newBlockContext(e->currentStackFrame, index)->asReturnedValue(); + auto name = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex]; + engine->currentStackFrame->jsFrame->context = ExecutionContext::newCatchContext(engine->currentStackFrame, blockIndex, name)->asReturnedValue(); } -ReturnedValue Runtime::method_cloneBlockContext(ExecutionContext *previous) +void Runtime::PushBlockContext::call(ExecutionEngine *engine, int index) { - return ExecutionContext::cloneBlockContext(static_cast<Heap::CallContext *>(previous->d()))->asReturnedValue(); + engine->currentStackFrame->jsFrame->context = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue(); } +void Runtime::CloneBlockContext::call(ExecutionEngine *engine) +{ + auto frame = engine->currentStackFrame; + auto context = static_cast<Heap::CallContext *>(frame->jsFrame->context.m()); + frame->jsFrame->context = + ExecutionContext::cloneBlockContext(engine, context)->asReturnedValue(); +} -ReturnedValue Runtime::method_createScriptContext(ExecutionEngine *engine, int index) +void Runtime::PushScriptContext::call(ExecutionEngine *engine, int index) { Q_ASSERT(engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_GlobalContext || engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_QmlContext); ReturnedValue c = ExecutionContext::newBlockContext(engine->currentStackFrame, index)->asReturnedValue(); engine->setScriptContext(c); - return c; + engine->currentStackFrame->jsFrame->context = c; } -ReturnedValue Runtime::method_popScriptContext(ExecutionEngine *engine) +void Runtime::PopScriptContext::call(ExecutionEngine *engine) { ReturnedValue root = engine->rootContext()->asReturnedValue(); engine->setScriptContext(root); - return root; + engine->currentStackFrame->jsFrame->context = root; } -void Runtime::method_throwReferenceError(ExecutionEngine *engine, int nameIndex) +void Runtime::ThrowReferenceError::call(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); engine->throwReferenceError(name); } -void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex) +void Runtime::ThrowOnNullOrUndefined::call(ExecutionEngine *engine, const Value &v) +{ + if (v.isNullOrUndefined()) + engine->throwTypeError(); +} + +ReturnedValue Runtime::ConvertThisToObject::call(ExecutionEngine *engine, const Value &t) +{ + if (!t.isObject()) { + if (t.isNullOrUndefined()) { + return engine->globalObject->asReturnedValue(); + } else { + return t.toObject(engine)->asReturnedValue(); + } + } + return t.asReturnedValue(); +} + +void Runtime::DeclareVar::call(ExecutionEngine *engine, Bool deletable, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).createMutableBinding(name, deletable); } -ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *values, uint length) +ReturnedValue Runtime::ArrayLiteral::call(ExecutionEngine *engine, Value *values, uint length) { return engine->newArrayObject(values, length)->asReturnedValue(); } -ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId, const QV4::Value *args, int argc) +ReturnedValue Runtime::ObjectLiteral::call(ExecutionEngine *engine, int classId, QV4::Value args[], int argc) { Scope scope(engine); Scoped<InternalClass> klass(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeClasses[classId]); @@ -1796,7 +1872,8 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId return o.asReturnedValue(); } -ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classIndex, const Value &superClass, const Value *computedNames) +ReturnedValue Runtime::CreateClass::call(ExecutionEngine *engine, int classIndex, + const Value &superClass, Value computedNames[]) { const CompiledData::CompilationUnit *unit = engine->currentStackFrame->v4Function->compilationUnit; const QV4::CompiledData::Class *cls = unit->unitData()->classAt(classIndex); @@ -1898,20 +1975,20 @@ ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classInde return constructor->asReturnedValue(); } -QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine) +QV4::ReturnedValue Runtime::CreateMappedArgumentsObject::call(ExecutionEngine *engine) { Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext); Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_ArgumentsObject); return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue(); } -QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine *engine) +QV4::ReturnedValue Runtime::CreateUnmappedArgumentsObject::call(ExecutionEngine *engine) { Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_StrictArgumentsObject); return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue(); } -QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, int argIndex) +QV4::ReturnedValue Runtime::CreateRestParameter::call(ExecutionEngine *engine, int argIndex) { const Value *values = engine->currentStackFrame->originalArguments + argIndex; int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex; @@ -1920,14 +1997,32 @@ QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, return engine->newArrayObject(values, nValues)->asReturnedValue(); } -ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id) +ReturnedValue Runtime::RegexpLiteral::call(ExecutionEngine *engine, int id) { Heap::RegExpObject *ro = engine->newRegExpObject(engine->currentStackFrame->v4Function->compilationUnit->runtimeRegularExpressions[id].as<RegExp>()); return ro->asReturnedValue(); } + +ReturnedValue Runtime::ToObject::call(ExecutionEngine *engine, const Value &obj) +{ + if (obj.isObject()) + return obj.asReturnedValue(); + + return obj.toObject(engine)->asReturnedValue(); +} + +Bool Runtime::ToBoolean::call(const Value &obj) +{ + return obj.toBoolean(); +} + +ReturnedValue Runtime::ToNumber::call(ExecutionEngine *, const Value &v) +{ + return Encode(v.toNumber()); +} #endif // V4_BOOTSTRAP -ReturnedValue Runtime::method_uMinus(const Value &value) +ReturnedValue Runtime::UMinus::call(const Value &value) { TRACE1(value); @@ -1944,7 +2039,7 @@ ReturnedValue Runtime::method_uMinus(const Value &value) // binary operators #ifndef V4_BOOTSTRAP -ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right) +ReturnedValue Runtime::Add::call(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); @@ -1956,7 +2051,7 @@ ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, co return RuntimeHelpers::addHelper(engine, left, right); } -ReturnedValue Runtime::method_sub(const Value &left, const Value &right) +ReturnedValue Runtime::Sub::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -1969,7 +2064,7 @@ ReturnedValue Runtime::method_sub(const Value &left, const Value &right) return Value::fromDouble(lval - rval).asReturnedValue(); } -ReturnedValue Runtime::method_mul(const Value &left, const Value &right) +ReturnedValue Runtime::Mul::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -1982,7 +2077,7 @@ ReturnedValue Runtime::method_mul(const Value &left, const Value &right) return Value::fromDouble(lval * rval).asReturnedValue(); } -ReturnedValue Runtime::method_div(const Value &left, const Value &right) +ReturnedValue Runtime::Div::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2003,7 +2098,7 @@ ReturnedValue Runtime::method_div(const Value &left, const Value &right) return Value::fromDouble(lval / rval).asReturnedValue(); } -ReturnedValue Runtime::method_mod(const Value &left, const Value &right) +ReturnedValue Runtime::Mod::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2024,7 +2119,43 @@ ReturnedValue Runtime::method_mod(const Value &left, const Value &right) return Value::fromDouble(std::fmod(lval, rval)).asReturnedValue(); } -ReturnedValue Runtime::method_shl(const Value &left, const Value &right) +ReturnedValue Runtime::Exp::call(const Value &base, const Value &exp) +{ + double b = base.toNumber(); + double e = exp.toNumber(); + if (qt_is_inf(e) && (b == 1 || b == -1)) + return Encode(qt_snan()); + return Encode(pow(b,e)); +} + +ReturnedValue Runtime::BitAnd::call(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32(); + return Encode((int)(lval & rval)); +} + +ReturnedValue Runtime::BitOr::call(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32(); + return Encode((int)(lval | rval)); +} + +ReturnedValue Runtime::BitXor::call(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32(); + return Encode((int)(lval ^ rval)); +} + +ReturnedValue Runtime::Shl::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2033,7 +2164,7 @@ ReturnedValue Runtime::method_shl(const Value &left, const Value &right) return Encode((int)(lval << rval)); } -ReturnedValue Runtime::method_shr(const Value &left, const Value &right) +ReturnedValue Runtime::Shr::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2042,7 +2173,7 @@ ReturnedValue Runtime::method_shr(const Value &left, const Value &right) return Encode((int)(lval >> rval)); } -ReturnedValue Runtime::method_ushr(const Value &left, const Value &right) +ReturnedValue Runtime::UShr::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2055,35 +2186,35 @@ ReturnedValue Runtime::method_ushr(const Value &left, const Value &right) #endif // V4_BOOTSTRAP -ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right) +ReturnedValue Runtime::GreaterThan::call(const Value &left, const Value &right) { TRACE2(left, right); - bool r = method_compareGreaterThan(left, right); + bool r = CompareGreaterThan::call(left, right); return Encode(r); } -ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right) +ReturnedValue Runtime::LessThan::call(const Value &left, const Value &right) { TRACE2(left, right); - bool r = method_compareLessThan(left, right); + bool r = CompareLessThan::call(left, right); return Encode(r); } -ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right) +ReturnedValue Runtime::GreaterEqual::call(const Value &left, const Value &right) { TRACE2(left, right); - bool r = method_compareGreaterEqual(left, right); + bool r = CompareGreaterEqual::call(left, right); return Encode(r); } -ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right) +ReturnedValue Runtime::LessEqual::call(const Value &left, const Value &right) { TRACE2(left, right); - bool r = method_compareLessEqual(left, right); + bool r = CompareLessEqual::call(left, right); return Encode(r); } @@ -2107,7 +2238,7 @@ struct LazyScope } }; -Bool Runtime::method_compareEqual(const Value &left, const Value &right) +Bool Runtime::CompareEqual::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2216,23 +2347,23 @@ Bool Runtime::method_compareEqual(const Value &left, const Value &right) } } -ReturnedValue Runtime::method_equal(const Value &left, const Value &right) +ReturnedValue Runtime::Equal::call(const Value &left, const Value &right) { TRACE2(left, right); - bool r = method_compareEqual(left, right); + bool r = CompareEqual::call(left, right); return Encode(r); } -ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right) +ReturnedValue Runtime::NotEqual::call(const Value &left, const Value &right) { TRACE2(left, right); - bool r = !method_compareEqual(left, right); + bool r = !CompareEqual::call(left, right); return Encode(r); } -ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right) +ReturnedValue Runtime::StrictEqual::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2240,7 +2371,7 @@ ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right) return Encode(r); } -ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right) +ReturnedValue Runtime::StrictNotEqual::call(const Value &left, const Value &right) { TRACE2(left, right); @@ -2248,21 +2379,21 @@ ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &rig return Encode(r); } -Bool Runtime::method_compareNotEqual(const Value &left, const Value &right) +Bool Runtime::CompareNotEqual::call(const Value &left, const Value &right) { TRACE2(left, right); - return !Runtime::method_compareEqual(left, right); + return !Runtime::CompareEqual::call(left, right); } -Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right) +Bool Runtime::CompareStrictEqual::call(const Value &left, const Value &right) { TRACE2(left, right); return RuntimeHelpers::strictEqual(left, right); } -Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right) +Bool Runtime::CompareStrictNotEqual::call(const Value &left, const Value &right) { TRACE2(left, right); diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 2be3ebf012..72af90d1dc 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -114,8 +114,6 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { static Bool strictEqual(const Value &x, const Value &y); static ReturnedValue addHelper(ExecutionEngine *engine, const Value &left, const Value &right); - - static ReturnedValue getTemplateObject(Function *function, int index); }; diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index ceec13a3bb..86cbccde23 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -57,173 +57,450 @@ QT_BEGIN_NAMESPACE namespace QV4 { typedef uint Bool; -struct NoThrowEngine; -namespace { -template <typename T> -struct ExceptionCheck { - enum { NeedsCheck = 1 }; -}; -// push_catch and pop context methods shouldn't check for exceptions -template <> -struct ExceptionCheck<void (*)(QV4::NoThrowEngine *)> { - enum { NeedsCheck = 0 }; -}; -template <typename A> -struct ExceptionCheck<void (*)(A, QV4::NoThrowEngine)> { - enum { NeedsCheck = 0 }; -}; -template <> -struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *)> { - enum { NeedsCheck = 0 }; -}; -template <typename A> -struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A)> { - enum { NeedsCheck = 0 }; -}; -template <typename A, typename B> -struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A, B)> { - enum { NeedsCheck = 0 }; -}; -template <typename A, typename B, typename C> -struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { - enum { NeedsCheck = 0 }; -}; -} // anonymous namespace - -#define FOR_EACH_RUNTIME_METHOD(F) \ - /* call */ \ - F(ReturnedValue, callGlobalLookup, (ExecutionEngine *engine, uint index, Value *argv, int argc)) \ - F(ReturnedValue, callQmlContextPropertyLookup, (ExecutionEngine *engine, uint index, Value *argv, int argc)) \ - F(ReturnedValue, callName, (ExecutionEngine *engine, int nameIndex, Value *argv, int argc)) \ - F(ReturnedValue, callProperty, (ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)) \ - F(ReturnedValue, callPropertyLookup, (ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)) \ - F(ReturnedValue, callElement, (ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)) \ - F(ReturnedValue, callValue, (ExecutionEngine *engine, const Value &func, Value *argv, int argc)) \ - F(ReturnedValue, callWithReceiver, (ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)) \ - F(ReturnedValue, callPossiblyDirectEval, (ExecutionEngine *engine, Value *argv, int argc)) \ - F(ReturnedValue, callWithSpread, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \ - F(ReturnedValue, tailCall, (CppStackFrame *frame, ExecutionEngine *engine)) \ - \ - /* construct */ \ - F(ReturnedValue, construct, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \ - F(ReturnedValue, constructWithSpread, (ExecutionEngine *engine, const Value &func, const Value &newTarget, Value *argv, int argc)) \ - \ - /* load & store */ \ - F(void, storeNameStrict, (ExecutionEngine *engine, int nameIndex, const Value &value)) \ - F(void, storeNameSloppy, (ExecutionEngine *engine, int nameIndex, const Value &value)) \ - F(void, storeProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)) \ - F(void, storeElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)) \ - F(void, storeElement_traced, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value, quint8 *traceSlot)) \ - F(ReturnedValue, loadProperty, (ExecutionEngine *engine, const Value &object, int nameIndex)) \ - F(ReturnedValue, loadName, (ExecutionEngine *engine, int nameIndex)) \ - F(ReturnedValue, loadElement, (ExecutionEngine *engine, const Value &object, const Value &index)) \ - F(ReturnedValue, loadElement_traced, (ExecutionEngine *engine, const Value &object, const Value &index, quint8 *traceSlot)) \ - F(ReturnedValue, loadSuperProperty, (ExecutionEngine *engine, const Value &property)) \ - F(void, storeSuperProperty, (ExecutionEngine *engine, const Value &property, const Value &value)) \ - F(ReturnedValue, loadSuperConstructor, (ExecutionEngine *engine, const Value &t)) \ - \ - /* typeof */ \ - F(ReturnedValue, typeofValue, (ExecutionEngine *engine, const Value &val)) \ - F(ReturnedValue, typeofName, (ExecutionEngine *engine, int nameIndex)) \ - \ - /* delete */ \ - F(bool, deleteProperty, (ExecutionEngine *engine, const Value &base, const Value &index)) \ - F(bool, deleteName, (ExecutionEngine *engine, int nameIndex)) \ - \ - /* exceptions & scopes */ \ - F(void, throwException, (ExecutionEngine *engine, const Value &value)) \ - F(ReturnedValue, createWithContext, (ExecutionEngine *, Value *jsStackFrame)) \ - F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)) \ - F(ReturnedValue, createBlockContext, (ExecutionContext *parent, int index)) \ - F(ReturnedValue, createScriptContext, (ExecutionEngine *engine, int index)) \ - F(ReturnedValue, cloneBlockContext, (ExecutionContext *previous)) \ - F(ReturnedValue, popScriptContext, (ExecutionEngine *engine)) \ - F(void, throwReferenceError, (ExecutionEngine *engine, int nameIndex)) \ - \ - /* closures */ \ - F(ReturnedValue, closure, (ExecutionEngine *engine, int functionId)) \ - \ - /* function header */ \ - F(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)) \ - F(ReturnedValue, createMappedArgumentsObject, (ExecutionEngine *engine)) \ - F(ReturnedValue, createUnmappedArgumentsObject, (ExecutionEngine *engine)) \ - F(ReturnedValue, createRestParameter, (ExecutionEngine *engine, int argIndex)) \ - \ - /* literals */ \ - F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \ - F(ReturnedValue, objectLiteral, (ExecutionEngine *engine, int classId, const Value *args, int argc)) \ - F(ReturnedValue, createClass, (ExecutionEngine *engine, int classIndex, const Value &heritage, const Value *computedNames)) \ - \ - /* for-in, for-of and array destructuring */ \ - F(ReturnedValue, getIterator, (ExecutionEngine *engine, const Value &in, int iterator)) \ - F(ReturnedValue, iteratorNext, (ExecutionEngine *engine, const Value &iterator, Value *value)) \ - F(ReturnedValue, iteratorNextForYieldStar, (ExecutionEngine *engine, const Value &received, const Value &iterator, Value *object)) \ - F(ReturnedValue, iteratorClose, (ExecutionEngine *engine, const Value &iterator, const Value &done)) \ - F(ReturnedValue, destructureRestElement, (ExecutionEngine *engine, const Value &iterator)) \ - \ - /* unary operators */ \ - F(ReturnedValue, uMinus, (const Value &value)) \ - \ - /* binary operators */ \ - F(ReturnedValue, instanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \ - F(ReturnedValue, in, (ExecutionEngine *engine, const Value &left, const Value &right)) \ - F(ReturnedValue, add, (ExecutionEngine *engine, const Value &left, const Value &right)) \ - F(ReturnedValue, sub, (const Value &left, const Value &right)) \ - F(ReturnedValue, mul, (const Value &left, const Value &right)) \ - F(ReturnedValue, div, (const Value &left, const Value &right)) \ - F(ReturnedValue, mod, (const Value &left, const Value &right)) \ - F(ReturnedValue, shl, (const Value &left, const Value &right)) \ - F(ReturnedValue, shr, (const Value &left, const Value &right)) \ - F(ReturnedValue, ushr, (const Value &left, const Value &right)) \ - F(ReturnedValue, greaterThan, (const Value &left, const Value &right)) \ - F(ReturnedValue, lessThan, (const Value &left, const Value &right)) \ - F(ReturnedValue, greaterEqual, (const Value &left, const Value &right)) \ - F(ReturnedValue, lessEqual, (const Value &left, const Value &right)) \ - F(ReturnedValue, equal, (const Value &left, const Value &right)) \ - F(ReturnedValue, notEqual, (const Value &left, const Value &right)) \ - F(ReturnedValue, strictEqual, (const Value &left, const Value &right)) \ - F(ReturnedValue, strictNotEqual, (const Value &left, const Value &right)) \ - \ - /* comparisons */ \ - F(Bool, compareGreaterThan, (const Value &l, const Value &r)) \ - F(Bool, compareLessThan, (const Value &l, const Value &r)) \ - F(Bool, compareGreaterEqual, (const Value &l, const Value &r)) \ - F(Bool, compareLessEqual, (const Value &l, const Value &r)) \ - F(Bool, compareEqual, (const Value &left, const Value &right)) \ - F(Bool, compareNotEqual, (const Value &left, const Value &right)) \ - F(Bool, compareStrictEqual, (const Value &left, const Value &right)) \ - F(Bool, compareStrictNotEqual, (const Value &left, const Value &right)) \ - \ - F(Bool, compareInstanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \ - F(Bool, compareIn, (ExecutionEngine *engine, const Value &left, const Value &right)) \ - \ - F(ReturnedValue, regexpLiteral, (ExecutionEngine *engine, int id)) struct Q_QML_PRIVATE_EXPORT Runtime { - Runtime(); - typedef ReturnedValue (*UnaryOperation)(const Value &value); typedef ReturnedValue (*BinaryOperation)(const Value &left, const Value &right); - typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *engine, const Value &left, const Value &right); + typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *, const Value &left, const Value &right); + + enum class Throws { No, Yes }; + enum class ChangesContext { No, Yes }; + enum class Pure { No, Yes }; + enum class LastArgumentIsOutputValue { No, Yes }; + + template<Throws t, ChangesContext c = ChangesContext::No, Pure p = Pure::No, + LastArgumentIsOutputValue out = LastArgumentIsOutputValue::No> + struct Method + { + static constexpr bool throws = t == Throws::Yes; + static constexpr bool changesContext = c == ChangesContext::Yes; + static constexpr bool pure = p == Pure::Yes; + static constexpr bool lastArgumentIsOutputValue = out == LastArgumentIsOutputValue::Yes; + }; + using PureMethod = Method<Throws::No, ChangesContext::No, Pure::Yes>; + using IteratorMethod = Method<Throws::Yes, ChangesContext::No, Pure::No, + LastArgumentIsOutputValue::Yes>; + + /* call */ + struct Q_QML_PRIVATE_EXPORT CallGlobalLookup : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, uint, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallQmlContextPropertyLookup : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, uint, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallName : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, int, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallProperty : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, int, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallPropertyLookup : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, uint, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallElement : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallValue : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallWithReceiver : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallPossiblyDirectEval : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CallWithSpread : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT TailCall : Method<Throws::Yes> + { + static ReturnedValue call(CppStackFrame *, ExecutionEngine *); + }; + + /* construct */ + struct Q_QML_PRIVATE_EXPORT Construct : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT ConstructWithSpread : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value[], int); + }; + + /* load & store */ + struct Q_QML_PRIVATE_EXPORT StoreNameStrict : Method<Throws::Yes> + { + static void call(ExecutionEngine *, int, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StoreNameSloppy : Method<Throws::Yes> + { + static void call(ExecutionEngine *, int, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StoreProperty : Method<Throws::Yes> + { + static void call(ExecutionEngine *, const Value &, int, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StoreElement : Method<Throws::Yes> + { + static void call(ExecutionEngine *, const Value &, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StoreElement_traced : Method<Throws::Yes> + { + static void call(ExecutionEngine *, const Value &, const Value &, const Value &, quint8 *); + }; + struct Q_QML_PRIVATE_EXPORT LoadProperty : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, int); + }; + struct Q_QML_PRIVATE_EXPORT LoadName : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, int); + }; + struct Q_QML_PRIVATE_EXPORT LoadElement : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT LoadElement_Traced : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, quint8 *); + }; + struct Q_QML_PRIVATE_EXPORT LoadSuperProperty : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StoreSuperProperty : Method<Throws::Yes> + { + static void call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT LoadSuperConstructor : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT LoadGlobalLookup : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, Function *, int); + }; + struct Q_QML_PRIVATE_EXPORT LoadQmlContextPropertyLookup : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, uint); + }; + struct Q_QML_PRIVATE_EXPORT GetLookup : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, Function *, const Value &, int); + }; + struct Q_QML_PRIVATE_EXPORT SetLookupStrict : Method<Throws::Yes> + { + static void call(Function *, const Value &, int, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT SetLookupSloppy : Method<Throws::Yes> + { + static void call(Function *, const Value &, int, const Value &); + }; -#define DEFINE_RUNTIME_METHOD_ENUM(returnvalue, name, args) name, - enum RuntimeMethods { - FOR_EACH_RUNTIME_METHOD(DEFINE_RUNTIME_METHOD_ENUM) - RuntimeMethodCount, - InvalidRuntimeMethod = RuntimeMethodCount + /* typeof */ + struct Q_QML_PRIVATE_EXPORT TypeofValue : PureMethod + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT TypeofName : Method<Throws::No> + { + static ReturnedValue call(ExecutionEngine *, int); }; -#undef DEFINE_RUNTIME_METHOD_ENUM - void *runtimeMethods[RuntimeMethodCount]; + /* delete */ + struct Q_QML_PRIVATE_EXPORT DeleteProperty_NoThrow : Method<Throws::No> + { + static Bool call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT DeleteProperty : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, Function *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT DeleteName_NoThrow : Method<Throws::No> + { + static Bool call(ExecutionEngine *, int); + }; + struct Q_QML_PRIVATE_EXPORT DeleteName : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, Function *, int); + }; - static uint runtimeMethodOffset(RuntimeMethods method) { return method*QT_POINTER_SIZE; } + /* exceptions & scopes */ + struct Q_QML_PRIVATE_EXPORT ThrowException : Method<Throws::Yes> + { + static void call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT PushCallContext : Method<Throws::No, ChangesContext::Yes> + { + static void call(CppStackFrame *); + }; + struct Q_QML_PRIVATE_EXPORT PushWithContext : Method<Throws::Yes, ChangesContext::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT PushCatchContext : Method<Throws::No, ChangesContext::Yes> + { + static void call(ExecutionEngine *, int, int); + }; + struct Q_QML_PRIVATE_EXPORT PushBlockContext : Method<Throws::No, ChangesContext::Yes> + { + static void call(ExecutionEngine *, int); + }; + struct Q_QML_PRIVATE_EXPORT CloneBlockContext : Method<Throws::No, ChangesContext::Yes> + { + static void call(ExecutionEngine *); + }; + struct Q_QML_PRIVATE_EXPORT PushScriptContext : Method<Throws::No, ChangesContext::Yes> + { + static void call(ExecutionEngine *, int); + }; + struct Q_QML_PRIVATE_EXPORT PopScriptContext : Method<Throws::No, ChangesContext::Yes> + { + static void call(ExecutionEngine *); + }; + struct Q_QML_PRIVATE_EXPORT ThrowReferenceError : Method<Throws::Yes> + { + static void call(ExecutionEngine *, int); + }; + struct Q_QML_PRIVATE_EXPORT ThrowOnNullOrUndefined : Method<Throws::Yes> + { + static void call(ExecutionEngine *, const Value &); + }; -#define RUNTIME_METHOD(returnvalue, name, args) \ - typedef returnvalue (*Method_##name)args; \ - enum { Method_##name##_NeedsExceptionCheck = ExceptionCheck<Method_##name>::NeedsCheck }; \ - static returnvalue method_##name args; - FOR_EACH_RUNTIME_METHOD(RUNTIME_METHOD) -#undef RUNTIME_METHOD + /* closures */ + struct Q_QML_PRIVATE_EXPORT Closure : Method<Throws::No> + { + static ReturnedValue call(ExecutionEngine *, int); + }; + + /* Function header */ + struct Q_QML_PRIVATE_EXPORT ConvertThisToObject : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT DeclareVar : Method<Throws::Yes> + { + static void call(ExecutionEngine *, Bool, int); + }; + struct Q_QML_PRIVATE_EXPORT CreateMappedArgumentsObject : Method<Throws::No> + { + static ReturnedValue call(ExecutionEngine *); + }; + struct Q_QML_PRIVATE_EXPORT CreateUnmappedArgumentsObject : Method<Throws::No> + { + static ReturnedValue call(ExecutionEngine *); + }; + struct Q_QML_PRIVATE_EXPORT CreateRestParameter : PureMethod + { + static ReturnedValue call(ExecutionEngine *, int); + }; + + /* literals */ + struct Q_QML_PRIVATE_EXPORT ArrayLiteral : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, Value[], uint); + }; + struct Q_QML_PRIVATE_EXPORT ObjectLiteral : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, int, Value[], int); + }; + struct Q_QML_PRIVATE_EXPORT CreateClass : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, int, const Value &, Value[]); + }; + + /* for-in, for-of and array destructuring */ + struct Q_QML_PRIVATE_EXPORT GetIterator : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, int); + }; + struct Q_QML_PRIVATE_EXPORT IteratorNext : IteratorMethod + { + static ReturnedValue call(ExecutionEngine *, const Value &, Value *); + }; + struct Q_QML_PRIVATE_EXPORT IteratorNextForYieldStar : IteratorMethod + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &, Value *); + }; + struct Q_QML_PRIVATE_EXPORT IteratorClose : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT DestructureRestElement : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + + /* conversions */ + struct Q_QML_PRIVATE_EXPORT ToObject : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT ToBoolean : PureMethod + { + static Bool call(const Value &); + }; + struct Q_QML_PRIVATE_EXPORT ToNumber : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &); + }; + /* unary operators */ + struct Q_QML_PRIVATE_EXPORT UMinus : Method<Throws::Yes> + { + static ReturnedValue call(const Value &); + }; + + /* binary operators */ + struct Q_QML_PRIVATE_EXPORT Instanceof : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT In : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Add : Method<Throws::Yes> + { + static ReturnedValue call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Sub : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Mul : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Div : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Mod : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Exp : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT BitAnd : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT BitOr : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT BitXor : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Shl : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Shr : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT UShr : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT GreaterThan : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT LessThan : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT GreaterEqual : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT LessEqual : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT Equal : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT NotEqual : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StrictEqual : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT StrictNotEqual : Method<Throws::Yes> + { + static ReturnedValue call(const Value &, const Value &); + }; + + /* comparisons */ + struct Q_QML_PRIVATE_EXPORT CompareGreaterThan : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareLessThan : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareGreaterEqual : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareLessEqual : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareEqual : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareNotEqual : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareStrictEqual : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareStrictNotEqual : Method<Throws::Yes> + { + static Bool call(const Value &, const Value &); + }; + + struct Q_QML_PRIVATE_EXPORT CompareInstanceof : Method<Throws::Yes> + { + static Bool call(ExecutionEngine *, const Value &, const Value &); + }; + struct Q_QML_PRIVATE_EXPORT CompareIn : Method<Throws::Yes> + { + static Bool call(ExecutionEngine *, const Value &, const Value &); + }; + + struct Q_QML_PRIVATE_EXPORT RegexpLiteral : PureMethod + { + static ReturnedValue call(ExecutionEngine *, int); + }; + struct Q_QML_PRIVATE_EXPORT GetTemplateObject : PureMethod + { + static ReturnedValue call(Function *, int); + }; struct StackOffsets { static const int tailCall_function = -1; @@ -234,7 +511,6 @@ struct Q_QML_PRIVATE_EXPORT Runtime { }; static_assert(std::is_standard_layout<Runtime>::value, "Runtime needs to be standard layout in order for us to be able to use offsetof"); -static_assert(offsetof(Runtime, runtimeMethods) == 0, "JIT expects this to be the first member"); static_assert(sizeof(Runtime::BinaryOperation) == sizeof(void*), "JIT expects a function pointer to fit into a regular pointer, for cross-compilation offset translation"); } // namespace QV4 diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index 50871a4d87..a84521e205 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -39,7 +39,6 @@ #include "qv4serialize_p.h" -#include <private/qv8engine_p.h> #if QT_CONFIG(qml_list_model) #include <private/qqmllistmodel_p.h> #include <private/qqmllistmodelworkeragent_p.h> @@ -375,7 +374,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(engine, agent)); // ### Find a better solution then the ugly property QQmlListModelWorkerAgent::VariantRef ref(agent); - QVariant var = qVariantFromValue(ref); + QVariant var = QVariant::fromValue(ref); QV4::ScopedValue v(scope, scope.engine->fromVariant(var)); QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref"))); rv->as<Object>()->defineReadonlyProperty(s, v); diff --git a/src/qml/jsruntime/qv4setobject.cpp b/src/qml/jsruntime/qv4setobject.cpp index 088ecbe30d..1664d1bd71 100644 --- a/src/qml/jsruntime/qv4setobject.cpp +++ b/src/qml/jsruntime/qv4setobject.cpp @@ -76,7 +76,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv, ScopedFunctionObject adder(scope, a->get(ScopedString(scope, scope.engine->newString(QString::fromLatin1("add"))))); if (!adder) return scope.engine->throwTypeError(); - ScopedObject iter(scope, Runtime::method_getIterator(scope.engine, iterable, true)); + ScopedObject iter(scope, Runtime::GetIterator::call(scope.engine, iterable, true)); CHECK_EXCEPTION(); if (!iter) return a.asReturnedValue(); @@ -84,7 +84,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv, Value *nextValue = scope.alloc(1); ScopedValue done(scope); forever { - done = Runtime::method_iteratorNext(scope.engine, iter, nextValue); + done = Runtime::IteratorNext::call(scope.engine, iter, nextValue); CHECK_EXCEPTION(); if (done->toBoolean()) return a.asReturnedValue(); @@ -92,7 +92,7 @@ ReturnedValue WeakSetCtor::construct(const FunctionObject *f, const Value *argv, adder->call(a, nextValue, 1); if (scope.engine->hasException) { ScopedValue falsey(scope, Encode(false)); - return Runtime::method_iteratorClose(scope.engine, iter, falsey); + return Runtime::IteratorClose::call(scope.engine, iter, falsey); } } } diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index faf7934c06..d83f021450 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -1595,7 +1595,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_toLocaleString(const Function R += separator; v = instance->get(k); - v = Runtime::method_callElement(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0); + v = Runtime::CallElement::call(scope.engine, v, *scope.engine->id_toLocaleString(), nullptr, 0); s = v->toString(scope.engine); if (scope.hasException()) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index b4a045edfb..da08841026 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -281,8 +281,22 @@ struct Q_QML_PRIVATE_EXPORT Value inline bool isUndefined() const { return _val == 0; } inline bool isDouble() const { return (_val >> IsDouble_Shift); } - inline bool isManaged() const { return _val && ((_val >> IsManagedOrUndefined_Shift) == 0); } - inline bool isManagedOrUndefined() const { return ((_val >> IsManagedOrUndefined_Shift) == 0); } + inline bool isManaged() const + { +#if QT_POINTER_SIZE == 4 + return value() && tag() == Managed_Type_Internal; +#else + return _val && ((_val >> IsManagedOrUndefined_Shift) == 0); +#endif + } + inline bool isManagedOrUndefined() const + { +#if QT_POINTER_SIZE == 4 + return tag() == Managed_Type_Internal; +#else + return ((_val >> IsManagedOrUndefined_Shift) == 0); +#endif + } inline bool isIntOrBool() const { return (_val >> IsIntegerOrBool_Shift) == 3; diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index e4d8bcaafc..e117e509ab 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -41,7 +41,6 @@ #include "qv4functionobject_p.h" #include "qv4objectproto_p.h" #include <private/qqmlvaluetypewrapper_p.h> -#include <private/qv8engine_p.h> #include <private/qv4qobjectwrapper_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index dd712a15d6..98e4f4f7b9 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -65,6 +65,8 @@ #undef COUNT_INSTRUCTIONS +enum { ShowWhenDeoptimiationHappens = 0 }; + extern "C" { // This is the interface to Qt Creator's (new) QML debugger. @@ -386,6 +388,18 @@ static inline void traceValue(ReturnedValue acc, Function *f, int slot) #endif } +static inline void traceIntValue(Function *f, int slot) +{ +#if QT_CONFIG(qml_tracing) + quint8 *traceInfo = f->traceInfo(slot); + Q_ASSERT(traceInfo); + *traceInfo |= quint8(ObservedTraceValues::Integer); +#else + Q_UNUSED(f); + Q_UNUSED(slot); +#endif +} + static inline void traceDoubleValue(Function *f, int slot) { #if QT_CONFIG(qml_tracing) @@ -488,13 +502,17 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine) #ifdef V4_ENABLE_JIT if (debugger == nullptr) { if (function->jittedCode == nullptr) { - if (engine->canJIT(function)) - QV4::JIT::BaselineJIT(function).generate(); - else + if (engine->canJIT(function)) { +#if QT_CONFIG(qml_tracing) + if (function->tracingEnabled()) + runTracingJit(function); + else +#endif + QV4::JIT::BaselineJIT(function).generate(); + } else { ++function->interpreterCallCount; + } } - if (function->jittedCode != nullptr) - return function->jittedCode(frame, engine); } #endif // V4_ENABLE_JIT @@ -502,7 +520,29 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine) if (debugger) debugger->enteringFunction(); - ReturnedValue result = interpret(frame, engine, function->codeData); + ReturnedValue result; + if (function->jittedCode != nullptr && debugger == nullptr) { + result = function->jittedCode(frame, engine); + if (QV4::Value::fromReturnedValue(result).isEmpty()) { // de-optimize! + if (ShowWhenDeoptimiationHappens) { + // This is debug code, which is disabled by default, and completely removed by the + // compiler. + fprintf(stderr, "*********************** DEOPT! %s ***********************\n" + "*** deopt IP: %d, line: %d\n", + function->name()->toQString().toUtf8().constData(), + frame->instructionPointer, + frame->lineNumber()); + } + delete function->codeRef; + function->codeRef = nullptr; + function->jittedCode = nullptr; + function->interpreterCallCount = 0; // reset to restart tracing: apparently we didn't have enough info before + result = interpret(frame, engine, function->codeData + frame->instructionPointer); + } + } else { + // interpreter + result = interpret(frame, engine, function->codeData); + } if (debugger) debugger->leavingFunction(result); @@ -607,16 +647,16 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(LoadRuntimeString) MOTH_BEGIN_INSTR(MoveRegExp) - STACK_VALUE(destReg) = Runtime::method_regexpLiteral(engine, regExpId); + STACK_VALUE(destReg) = Runtime::RegexpLiteral::call(engine, regExpId); MOTH_END_INSTR(MoveRegExp) MOTH_BEGIN_INSTR(LoadClosure) - acc = Runtime::method_closure(engine, value); + acc = Runtime::Closure::call(engine, value); MOTH_END_INSTR(LoadClosure) MOTH_BEGIN_INSTR(LoadName) STORE_IP(); - acc = Runtime::method_loadName(engine, name); + acc = Runtime::LoadName::call(engine, name); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(LoadName) @@ -640,14 +680,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(StoreNameStrict) STORE_IP(); STORE_ACC(); - Runtime::method_storeNameStrict(engine, name, accumulator); + Runtime::StoreNameStrict::call(engine, name, accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(StoreNameStrict) MOTH_BEGIN_INSTR(StoreNameSloppy) STORE_IP(); STORE_ACC(); - Runtime::method_storeNameSloppy(engine, name, accumulator); + Runtime::StoreNameSloppy::call(engine, name, accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(StoreNameSloppy) @@ -655,11 +695,11 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, STORE_IP(); STORE_ACC(); #if QT_CONFIG(qml_tracing) - acc = Runtime::method_loadElement_traced(engine, STACK_VALUE(base), accumulator, function->traceInfo(traceSlot)); + acc = Runtime::LoadElement_Traced::call(engine, STACK_VALUE(base), accumulator, function->traceInfo(traceSlot)); traceValue(acc, function, traceSlot); #else Q_UNUSED(traceSlot); - acc = Runtime::method_loadElement(engine, STACK_VALUE(base), accumulator); + acc = Runtime::LoadElement::call(engine, STACK_VALUE(base), accumulator); #endif CHECK_EXCEPTION; MOTH_END_INSTR(LoadElement) @@ -668,10 +708,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, STORE_IP(); STORE_ACC(); #if QT_CONFIG(qml_tracing) - Runtime::method_storeElement_traced(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator, function->traceInfo(traceSlot)); + Runtime::StoreElement_traced::call(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator, function->traceInfo(traceSlot)); #else Q_UNUSED(traceSlot); - Runtime::method_storeElement(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator); + Runtime::StoreElement::call(engine, STACK_VALUE(base), STACK_VALUE(index), accumulator); #endif CHECK_EXCEPTION; MOTH_END_INSTR(StoreElement) @@ -679,7 +719,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(LoadProperty) STORE_IP(); STORE_ACC(); - acc = Runtime::method_loadProperty(engine, accumulator, name); + acc = Runtime::LoadProperty::call(engine, accumulator, name); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(LoadProperty) @@ -706,7 +746,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(StoreProperty) STORE_IP(); STORE_ACC(); - Runtime::method_storeProperty(engine, STACK_VALUE(base), name, accumulator); + Runtime::StoreProperty::call(engine, STACK_VALUE(base), name, accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(StoreProperty) @@ -722,14 +762,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(LoadSuperProperty) STORE_IP(); STORE_ACC(); - acc = Runtime::method_loadSuperProperty(engine, STACK_VALUE(property)); + acc = Runtime::LoadSuperProperty::call(engine, STACK_VALUE(property)); CHECK_EXCEPTION; MOTH_END_INSTR(LoadSuperProperty) MOTH_BEGIN_INSTR(StoreSuperProperty) STORE_IP(); STORE_ACC(); - Runtime::method_storeSuperProperty(engine, STACK_VALUE(property), accumulator); + Runtime::StoreSuperProperty::call(engine, STACK_VALUE(property), accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(StoreSuperProperty) @@ -760,7 +800,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(IteratorNextForYieldStar) STORE_ACC(); - acc = Runtime::method_iteratorNextForYieldStar(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object)); + acc = Runtime::IteratorNextForYieldStar::call(engine, accumulator, STACK_VALUE(iterator), &STACK_VALUE(object)); CHECK_EXCEPTION; MOTH_END_INSTR(IteratorNextForYieldStar) @@ -791,7 +831,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(CallProperty) STORE_IP(); - acc = Runtime::method_callProperty(engine, stack + base, name, stack + argv, argc); + acc = Runtime::CallProperty::call(engine, stack[base], name, stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallProperty) @@ -826,42 +866,42 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(CallElement) STORE_IP(); - acc = Runtime::method_callElement(engine, stack + base, STACK_VALUE(index), stack + argv, argc); + acc = Runtime::CallElement::call(engine, stack[base], STACK_VALUE(index), stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallElement) MOTH_BEGIN_INSTR(CallName) STORE_IP(); - acc = Runtime::method_callName(engine, name, stack + argv, argc); + acc = Runtime::CallName::call(engine, name, stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallName) MOTH_BEGIN_INSTR(CallPossiblyDirectEval) STORE_IP(); - acc = Runtime::method_callPossiblyDirectEval(engine, stack + argv, argc); + acc = Runtime::CallPossiblyDirectEval::call(engine, stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallPossiblyDirectEval) MOTH_BEGIN_INSTR(CallGlobalLookup) STORE_IP(); - acc = Runtime::method_callGlobalLookup(engine, index, stack + argv, argc); + acc = Runtime::CallGlobalLookup::call(engine, index, stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallGlobalLookup) MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup) STORE_IP(); - acc = Runtime::method_callQmlContextPropertyLookup(engine, index, stack + argv, argc); + acc = Runtime::CallQmlContextPropertyLookup::call(engine, index, stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallQmlContextPropertyLookup) MOTH_BEGIN_INSTR(CallWithSpread) STORE_IP(); - acc = Runtime::method_callWithSpread(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc); + acc = Runtime::CallWithSpread::call(engine, STACK_VALUE(func), STACK_VALUE(thisObject), stack + argv, argc); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(CallWithSpread) @@ -872,19 +912,19 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, *engine->jsAlloca(1) = Primitive::fromInt32(argv); *engine->jsAlloca(1) = STACK_VALUE(thisObject); *engine->jsAlloca(1) = STACK_VALUE(func); - return Runtime::method_tailCall(frame, engine); + return Runtime::TailCall::call(frame, engine); CHECK_EXCEPTION; MOTH_END_INSTR(TailCall) MOTH_BEGIN_INSTR(Construct) STORE_IP(); - acc = Runtime::method_construct(engine, STACK_VALUE(func), ACC, stack + argv, argc); + acc = Runtime::Construct::call(engine, STACK_VALUE(func), ACC, stack + argv, argc); CHECK_EXCEPTION; MOTH_END_INSTR(Construct) MOTH_BEGIN_INSTR(ConstructWithSpread) STORE_IP(); - acc = Runtime::method_constructWithSpread(engine, STACK_VALUE(func), ACC, stack + argv, argc); + acc = Runtime::ConstructWithSpread::call(engine, STACK_VALUE(func), ACC, stack + argv, argc); CHECK_EXCEPTION; MOTH_END_INSTR(ConstructWithSpread) @@ -912,7 +952,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, if (ACC.isEmpty()) { STORE_IP(); STORE_ACC(); - Runtime::method_throwReferenceError(engine, name); + Runtime::ThrowReferenceError::call(engine, name); goto handleUnwind; } MOTH_END_INSTR(DeadTemporalZoneCheck) @@ -920,7 +960,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(ThrowException) STORE_IP(); STORE_ACC(); - Runtime::method_throwException(engine, accumulator); + Runtime::ThrowException::call(engine, accumulator); goto handleUnwind; MOTH_END_INSTR(ThrowException) @@ -938,40 +978,36 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(SetException) MOTH_BEGIN_INSTR(PushCatchContext) - ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context); - STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, index, name); + Runtime::PushCatchContext::call(engine, index, name); MOTH_END_INSTR(PushCatchContext) MOTH_BEGIN_INSTR(CreateCallContext) - stack[CallData::Context] = ExecutionContext::newCallContext(frame); + Runtime::PushCallContext::call(frame); MOTH_END_INSTR(CreateCallContext) MOTH_BEGIN_INSTR(PushWithContext) STORE_IP(); STORE_ACC(); - auto ctx = Runtime::method_createWithContext(engine, stack); + acc = Runtime::PushWithContext::call(engine, stack[CallData::Accumulator]); CHECK_EXCEPTION; - STACK_VALUE(CallData::Context) = ctx; MOTH_END_INSTR(PushWithContext) MOTH_BEGIN_INSTR(PushBlockContext) STORE_ACC(); - ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context); - STACK_VALUE(CallData::Context) = Runtime::method_createBlockContext(c, index); + Runtime::PushBlockContext::call(engine, index); MOTH_END_INSTR(PushBlockContext) MOTH_BEGIN_INSTR(CloneBlockContext) STORE_ACC(); - ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context); - STACK_VALUE(CallData::Context) = Runtime::method_cloneBlockContext(c); + Runtime::CloneBlockContext::call(engine); MOTH_END_INSTR(CloneBlockContext) MOTH_BEGIN_INSTR(PushScriptContext) - STACK_VALUE(CallData::Context) = Runtime::method_createScriptContext(engine, index); + Runtime::PushScriptContext::call(engine, index); MOTH_END_INSTR(PushScriptContext) MOTH_BEGIN_INSTR(PopScriptContext) - STACK_VALUE(CallData::Context) = Runtime::method_popScriptContext(engine); + Runtime::PopScriptContext::call(engine); MOTH_END_INSTR(PopScriptContext) MOTH_BEGIN_INSTR(PopContext) @@ -982,14 +1018,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(GetIterator) STORE_IP(); STORE_ACC(); - acc = Runtime::method_getIterator(engine, accumulator, iterator); + acc = Runtime::GetIterator::call(engine, accumulator, iterator); CHECK_EXCEPTION; MOTH_END_INSTR(GetIterator) MOTH_BEGIN_INSTR(IteratorNext) STORE_IP(); STORE_ACC(); - acc = Runtime::method_iteratorNext(engine, accumulator, &STACK_VALUE(value)); + acc = Runtime::IteratorNext::call(engine, accumulator, &STACK_VALUE(value)); STACK_VALUE(done) = acc; CHECK_EXCEPTION; MOTH_END_INSTR(IteratorNext) @@ -997,97 +1033,73 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(IteratorClose) STORE_IP(); STORE_ACC(); - acc = Runtime::method_iteratorClose(engine, accumulator, STACK_VALUE(done)); + acc = Runtime::IteratorClose::call(engine, accumulator, STACK_VALUE(done)); CHECK_EXCEPTION; MOTH_END_INSTR(IteratorClose) MOTH_BEGIN_INSTR(DestructureRestElement) STORE_IP(); STORE_ACC(); - acc = Runtime::method_destructureRestElement(engine, ACC); + acc = Runtime::DestructureRestElement::call(engine, ACC); CHECK_EXCEPTION; MOTH_END_INSTR(DestructureRestElement) MOTH_BEGIN_INSTR(DeleteProperty) - if (!Runtime::method_deleteProperty(engine, STACK_VALUE(base), STACK_VALUE(index))) { - if (function->isStrict()) { - STORE_IP(); - engine->throwTypeError(); - goto handleUnwind; - } - acc = Encode(false); - } else { - acc = Encode(true); - } + acc = Runtime::DeleteProperty::call(engine, function, STACK_VALUE(base), STACK_VALUE(index)); + CHECK_EXCEPTION; MOTH_END_INSTR(DeleteProperty) MOTH_BEGIN_INSTR(DeleteName) - if (!Runtime::method_deleteName(engine, name)) { - if (function->isStrict()) { - STORE_IP(); - QString n = function->compilationUnit->runtimeStrings[name]->toQString(); - engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(n)); - goto handleUnwind; - } - acc = Encode(false); - } else { - acc = Encode(true); - } + acc = Runtime::DeleteName::call(engine, function, name); + CHECK_EXCEPTION; MOTH_END_INSTR(DeleteName) MOTH_BEGIN_INSTR(TypeofName) - acc = Runtime::method_typeofName(engine, name); + acc = Runtime::TypeofName::call(engine, name); MOTH_END_INSTR(TypeofName) MOTH_BEGIN_INSTR(TypeofValue) STORE_ACC(); - acc = Runtime::method_typeofValue(engine, accumulator); + acc = Runtime::TypeofValue::call(engine, accumulator); MOTH_END_INSTR(TypeofValue) MOTH_BEGIN_INSTR(DeclareVar) - Runtime::method_declareVar(engine, isDeletable, varName); + Runtime::DeclareVar::call(engine, isDeletable, varName); MOTH_END_INSTR(DeclareVar) MOTH_BEGIN_INSTR(DefineArray) QV4::Value *arguments = stack + args; - acc = Runtime::method_arrayLiteral(engine, arguments, argc); + acc = Runtime::ArrayLiteral::call(engine, arguments, argc); MOTH_END_INSTR(DefineArray) MOTH_BEGIN_INSTR(DefineObjectLiteral) QV4::Value *arguments = stack + args; - acc = Runtime::method_objectLiteral(engine, internalClassId, arguments, argc); + acc = Runtime::ObjectLiteral::call(engine, internalClassId, arguments, argc); MOTH_END_INSTR(DefineObjectLiteral) MOTH_BEGIN_INSTR(CreateClass) - acc = Runtime::method_createClass(engine, classIndex, STACK_VALUE(heritage), stack + computedNames); + acc = Runtime::CreateClass::call(engine, classIndex, STACK_VALUE(heritage), stack + computedNames); MOTH_END_INSTR(CreateClass) MOTH_BEGIN_INSTR(CreateMappedArgumentsObject) - acc = Runtime::method_createMappedArgumentsObject(engine); + acc = Runtime::CreateMappedArgumentsObject::call(engine); MOTH_END_INSTR(CreateMappedArgumentsObject) MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject) - acc = Runtime::method_createUnmappedArgumentsObject(engine); + acc = Runtime::CreateUnmappedArgumentsObject::call(engine); MOTH_END_INSTR(CreateUnmappedArgumentsObject) MOTH_BEGIN_INSTR(CreateRestParameter) - acc = Runtime::method_createRestParameter(engine, argIndex); + acc = Runtime::CreateRestParameter::call(engine, argIndex); MOTH_END_INSTR(CreateRestParameter) MOTH_BEGIN_INSTR(ConvertThisToObject) - Value *t = &stack[CallData::This]; - if (!t->isObject()) { - if (t->isNullOrUndefined()) { - *t = engine->globalObject->asReturnedValue(); - } else { - *t = t->toObject(engine)->asReturnedValue(); - CHECK_EXCEPTION; - } - } + stack[CallData::This] = Runtime::ConvertThisToObject::call(engine, stack[CallData::This]); + CHECK_EXCEPTION; MOTH_END_INSTR(ConvertThisToObject) MOTH_BEGIN_INSTR(LoadSuperConstructor) - acc = Runtime::method_loadSuperConstructor(engine, stack[CallData::Function]); + acc = Runtime::LoadSuperConstructor::call(engine, stack[CallData::Function]); CHECK_EXCEPTION; MOTH_END_INSTR(LoadSuperConstructor) @@ -1168,7 +1180,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(left.int_32() == ACC.int_32()); } else { STORE_ACC(); - acc = Encode(bool(Runtime::method_compareEqual(left, accumulator))); + acc = Encode(bool(Runtime::CompareEqual::call(left, accumulator))); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpEq) @@ -1179,7 +1191,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(bool(left.int_32() != ACC.int_32())); } else { STORE_ACC(); - acc = Encode(bool(!Runtime::method_compareEqual(left, accumulator))); + acc = Encode(bool(!Runtime::CompareEqual::call(left, accumulator))); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpNe) @@ -1192,7 +1204,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(left.asDouble() > ACC.asDouble()); } else { STORE_ACC(); - acc = Encode(bool(Runtime::method_compareGreaterThan(left, accumulator))); + acc = Encode(bool(Runtime::CompareGreaterThan::call(left, accumulator))); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpGt) @@ -1205,7 +1217,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(left.asDouble() >= ACC.asDouble()); } else { STORE_ACC(); - acc = Encode(bool(Runtime::method_compareGreaterEqual(left, accumulator))); + acc = Encode(bool(Runtime::CompareGreaterEqual::call(left, accumulator))); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpGe) @@ -1218,7 +1230,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(left.asDouble() < ACC.asDouble()); } else { STORE_ACC(); - acc = Encode(bool(Runtime::method_compareLessThan(left, accumulator))); + acc = Encode(bool(Runtime::CompareLessThan::call(left, accumulator))); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpLt) @@ -1231,7 +1243,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(left.asDouble() <= ACC.asDouble()); } else { STORE_ACC(); - acc = Encode(bool(Runtime::method_compareLessEqual(left, accumulator))); + acc = Encode(bool(Runtime::CompareLessEqual::call(left, accumulator))); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpLe) @@ -1241,7 +1253,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, acc = Encode(true); } else { STORE_ACC(); - acc = Encode(bool(RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator))); + acc = Runtime::StrictEqual::call(STACK_VALUE(lhs), accumulator); CHECK_EXCEPTION; } MOTH_END_INSTR(CmpStrictEqual) @@ -1249,7 +1261,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(CmpStrictNotEqual) if (STACK_VALUE(lhs).rawValue() != ACC.rawValue() || ACC.isNaN()) { STORE_ACC(); - acc = Encode(!RuntimeHelpers::strictEqual(STACK_VALUE(lhs), accumulator)); + acc = Runtime::StrictNotEqual::call(STACK_VALUE(lhs), accumulator); CHECK_EXCEPTION; } else { acc = Encode(false); @@ -1258,13 +1270,13 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(CmpIn) STORE_ACC(); - acc = Runtime::method_in(engine, STACK_VALUE(lhs), accumulator); + acc = Runtime::In::call(engine, STACK_VALUE(lhs), accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(CmpIn) MOTH_BEGIN_INSTR(CmpInstanceOf) STORE_ACC(); - acc = Runtime::method_instanceof(engine, STACK_VALUE(lhs), ACC); + acc = Runtime::Instanceof::call(engine, STACK_VALUE(lhs), ACC); CHECK_EXCEPTION; MOTH_END_INSTR(CmpInstanceOf) @@ -1277,7 +1289,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(UNot) MOTH_BEGIN_INSTR(UPlus) - if (Q_UNLIKELY(!ACC.isNumber())) { + if (Q_LIKELY(ACC.isNumber())) { + if (ACC.isDouble()) + traceDoubleValue(function, traceSlot); + else + traceIntValue(function, traceSlot); + } else { acc = Encode(ACC.toNumberImpl()); CHECK_EXCEPTION; } @@ -1342,7 +1359,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, traceDoubleValue(function, traceSlot); } else { STORE_ACC(); - acc = Runtime::method_add(engine, left, accumulator); + acc = Runtime::Add::call(engine, left, accumulator); CHECK_EXCEPTION; traceOtherValue(function, traceSlot); } @@ -1357,7 +1374,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, traceDoubleValue(function, traceSlot); } else { STORE_ACC(); - acc = Runtime::method_sub(left, accumulator); + acc = Runtime::Sub::call(left, accumulator); CHECK_EXCEPTION; traceOtherValue(function, traceSlot); } @@ -1382,7 +1399,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, traceDoubleValue(function, traceSlot); } else { STORE_ACC(); - acc = Runtime::method_mul(left, accumulator); + acc = Runtime::Mul::call(left, accumulator); CHECK_EXCEPTION; traceOtherValue(function, traceSlot); } @@ -1390,13 +1407,13 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_BEGIN_INSTR(Div) STORE_ACC(); - acc = Runtime::method_div(STACK_VALUE(lhs), accumulator); + acc = Runtime::Div::call(STACK_VALUE(lhs), accumulator); CHECK_EXCEPTION; MOTH_END_INSTR(Div) MOTH_BEGIN_INSTR(Mod) STORE_ACC(); - acc = Runtime::method_mod(STACK_VALUE(lhs), accumulator); + acc = Runtime::Mod::call(STACK_VALUE(lhs), accumulator); CHECK_EXCEPTION; traceValue(acc, function, traceSlot); MOTH_END_INSTR(Mod) @@ -1485,7 +1502,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(ThrowOnNullOrUndefined) MOTH_BEGIN_INSTR(GetTemplateObject) - acc = RuntimeHelpers::getTemplateObject(function, index); + acc = Runtime::GetTemplateObject::call(function, index); MOTH_END_INSTR(GetTemplateObject) MOTH_BEGIN_INSTR(Debug) diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h index 8a76e60f20..4ac7120d36 100644 --- a/src/qml/jsruntime/qv4vme_moth_p.h +++ b/src/qml/jsruntime/qv4vme_moth_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE namespace QV4 { namespace Moth { +void runTracingJit(QV4::Function *function); + class VME { public: diff --git a/src/qml/jsruntime/qv4vtable_p.h b/src/qml/jsruntime/qv4vtable_p.h index aff1ae82d7..a4d91640c5 100644 --- a/src/qml/jsruntime/qv4vtable_p.h +++ b/src/qml/jsruntime/qv4vtable_p.h @@ -90,8 +90,8 @@ struct VTable typedef bool (*ResolveLookupSetter)(Object *, ExecutionEngine *, Lookup *, const Value &); const VTable * const parent; - quint32 inlinePropertyOffset : 16; - quint32 nInlineProperties : 16; + quint16 inlinePropertyOffset; + quint16 nInlineProperties; quint8 isExecutionContext; quint8 isString; quint8 isObject; |