From d49cc03df130353665edd89112fd4e1f3cdab9b6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 30 Sep 2013 22:41:12 +0200 Subject: [PATCH] Use SafeValue instead of Value in ScopedValue methods Change-Id: Ie463efe600d498ce77d4b9e8b48abcfd61c1ab78 Reviewed-by: Simon Hausmann --- src/imports/localstorage/plugin.cpp | 2 +- src/qml/jsruntime/qv4arrayobject.cpp | 4 +-- src/qml/jsruntime/qv4functionobject.cpp | 4 +-- src/qml/jsruntime/qv4jsonobject.cpp | 2 +- src/qml/jsruntime/qv4managed_p.h | 12 --------- src/qml/jsruntime/qv4objectproto.cpp | 2 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 +- src/qml/jsruntime/qv4regexpobject.cpp | 11 ++++---- src/qml/jsruntime/qv4runtime.cpp | 2 +- src/qml/jsruntime/qv4scopedvalue_p.h | 39 ++++++++++++++++----------- src/qml/jsruntime/qv4script.cpp | 2 +- src/qml/jsruntime/qv4sequenceobject.cpp | 4 +-- src/qml/jsruntime/qv4serialize.cpp | 2 +- src/qml/jsruntime/qv4value_def_p.h | 18 ++++++++++--- src/qml/jsruntime/qv4value_p.h | 12 --------- src/qml/qml/qqmlvmemetaobject.cpp | 2 +- src/qml/qml/qqmlxmlhttprequest.cpp | 2 +- src/qml/types/qqmldelegatemodel.cpp | 2 +- src/quick/items/context2d/qquickcontext2d.cpp | 16 +++++------ 19 files changed, 69 insertions(+), 71 deletions(-) diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index ca69499..c4e3d51 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -304,7 +304,7 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx) rows->sqlQuery = query; Scoped resultObject(scope, ctx->engine->newObject()); - result = resultObject.asValue(); + result = resultObject.asReturnedValue(); // XXX optimize ScopedString s(scope); ScopedValue v(scope); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 6f19597..92fa196 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -523,7 +523,7 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) --instance->arrayAttributes; *instance->arrayAttributes = Attr_Data; } - instance->arrayData->value = v; + instance->arrayData->value = v.asReturnedValue(); } else { uint idx = instance->allocArrayValue(v); instance->sparseArray->push_front(idx); @@ -643,7 +643,7 @@ ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx) ctx->throwTypeError(); ScopedCallData callData(scope, 3); - callData->args[2] = instance.asValue(); + callData->args[2] = instance; callData->thisObject = ctx->argument(1); ScopedValue r(scope); ScopedValue v(scope); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 11580b0..7ef0b96 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -144,7 +144,7 @@ void FunctionObject::init(const StringRef n, bool createProto) if (createProto) { Scoped proto(s, scope->engine->newObject(scope->engine->protoClass)); proto->memberData[Index_ProtoConstructor].value = this->asReturnedValue(); - memberData[Index_Prototype].value = proto.asValue(); + memberData[Index_Prototype].value = proto.asReturnedValue(); } ScopedValue v(s, n.asReturnedValue()); @@ -443,7 +443,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) ScopedObject obj(scope, v4->newObject(ic)); ExecutionContext *context = v4->current; - callData->thisObject = obj.asValue(); + callData->thisObject = obj.asReturnedValue(); ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData); ScopedValue result(scope); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 10d3075..2295fb5 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -285,7 +285,7 @@ bool JsonParser::parseMember(ObjectRef o) ScopedString s(scope, context->engine->newIdentifier(key)); Property *p = o->insertMember(s, Attr_Data); - p->value = val; + p->value = val.asReturnedValue(); END; return true; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index aca41be..d189c19 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -61,18 +61,6 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; } template inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} -template -struct Returned : private T -{ - static Returned *create(T *t) { return static_cast *>(t); } - T *getPointer() { return this; } - template - static T *getPointer(Returned *x) { return x->getPointer(); } - template - Returned *as() { return Returned::create(Returned::getPointer(this)); } - using T::asReturnedValue; -}; - #define Q_MANAGED \ public: \ Q_MANAGED_CHECK \ diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 4693834..21cbc8d 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -185,7 +185,7 @@ ReturnedValue ObjectPrototype::method_create(SimpleCallContext *ctx) newObject->setPrototype(O->asObject()); if (ctx->callData->argc > 1 && !ctx->callData->args[1].isUndefined()) { - ctx->callData->args[0] = newObject.asValue(); + ctx->callData->args[0] = newObject.asReturnedValue(); return method_defineProperties(ctx); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 90a1950..92cfdd8 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1640,7 +1640,7 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine) } else if (type == -1 || type == qMetaTypeId()) { QVariant value = *qvariantPtr; QV4::ScopedValue rv(scope, engine->fromVariant(value)); - if (QV4::QObjectWrapper *qobjectWrapper = rv->as()) { + if (QV4::Referenced qobjectWrapper = rv->asRef()) { if (QObject *object = qobjectWrapper->object()) QQmlData::get(object, true)->setImplicitDestructible(); } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 899938f..9c7fe94 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -243,7 +243,8 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) ScopedValue r(scope, callData->argument(0)); ScopedValue f(scope, callData->argument(1)); - if (RegExpObject *re = r->as()) { + Scoped re(scope, r); + if (re) { if (!f->isUndefined()) ctx->throwTypeError(); @@ -273,11 +274,11 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) } } - RegExp* re = RegExp::create(ctx->engine, pattern, ignoreCase, multiLine); - if (!re->isValid()) + RegExp *regexp = RegExp::create(ctx->engine, pattern, ignoreCase, multiLine); + if (!regexp->isValid()) ctx->throwSyntaxError(0); - return Encode(ctx->engine->newRegExpObject(re, global)); + return Encode(ctx->engine->newRegExpObject(regexp, global)); } ReturnedValue RegExpCtor::call(Managed *that, CallData *callData) @@ -341,7 +342,7 @@ ReturnedValue RegExpPrototype::method_exec(SimpleCallContext *ctx) array->setArrayLengthUnchecked(len); array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result); - array->memberData[Index_ArrayInput].value = arg; + array->memberData[Index_ArrayInput].value = arg.asReturnedValue(); if (r->global) r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index b5c48af..95fe39b 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -782,7 +782,7 @@ ReturnedValue __qmljs_call_property(ExecutionContext *context, const StringRef n } baseObject = __qmljs_convert_to_object(context, ValueRef(&callData->thisObject)); - callData->thisObject = baseObject.asValue(); + callData->thisObject = baseObject.asReturnedValue(); } Scoped o(scope, baseObject->get(name)); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index a1f6f4b..2e39f03 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -169,18 +169,14 @@ struct ScopedValue return *this; } - Value *operator->() { + SafeValue *operator->() { return ptr; } - const Value *operator->() const { + const SafeValue *operator->() const { return ptr; } - operator const Value &() const { - return *ptr; - } - ReturnedValue asReturnedValue() const { return ptr->val; } SafeValue *ptr; @@ -326,12 +322,6 @@ struct Scoped return static_cast(ptr->managed()); } - Value asValue() const { - if (ptr->m) - return *ptr; - return QV4::Primitive::undefinedValue(); - } - ReturnedValue asReturnedValue() const { #if QT_POINTER_SIZE == 8 return ptr->val ? ptr->val : Primitive::undefinedValue().asReturnedValue(); @@ -427,7 +417,7 @@ struct ValueRef { operator Value *() { return ptr; } - Value *operator->() { + SafeValue *operator->() { return ptr; } @@ -479,14 +469,14 @@ struct Referenced { } operator const T *() const { - return static_cast(ptr->managed()); + return ptr ? static_cast(ptr->managed()) : 0; } const T *operator->() const { return static_cast(ptr->managed()); } operator T *() { - return static_cast(ptr->managed()); + return ptr ? static_cast(ptr->managed()) : 0; } T *operator->() { return static_cast(ptr->managed()); @@ -496,6 +486,19 @@ struct Referenced { return static_cast(ptr->managed()); } ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); } + operator Returned *() const { return ptr ? Returned::create(getPointer()) : 0; } + + bool operator==(const Referenced &other) { + if (ptr == other.ptr) + return true; + return ptr && other.ptr && ptr->m == other.ptr->m; + } + bool operator!=(const Referenced &other) { + if (ptr == other.ptr) + return false; + return !ptr || ptr->m != other.ptr->m; + } + bool operator!() const { return !ptr || !ptr->managed(); } static Referenced null() { return Referenced(Null); } bool isNull() const { return !ptr; } @@ -642,6 +645,12 @@ inline Returned *SafeValue::as() return Returned::create(value_cast(*this)); } +template inline +Referenced SafeValue::asRef() +{ + return Referenced(*this); +} + template inline Safe &Safe::operator =(T *t) { diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 2350224..0dddbe8 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -152,7 +152,7 @@ Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit vmFunction = compilationUnit->linkToEngine(v4); Q_ASSERT(vmFunction); Scope valueScope(v4); - ScopedValue holder(valueScope, Value::fromObject(new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit))); + ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); compilationUnitHolder = holder; } else vmFunction = 0; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 10293a7..5c8f7db 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -575,7 +575,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId) #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId()) { \ - QV4::Scoped obj(scope, QV4::Value::fromObject(new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex))); \ + QV4::Scoped obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex)); \ return obj.asReturnedValue(); \ } else @@ -593,7 +593,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s #define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId()) { \ - QV4::Scoped obj(scope, QV4::Value::fromObject(new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value()))); \ + QV4::Scoped obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value())); \ return obj.asReturnedValue(); \ } else diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index f775a44..7d3214e 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -392,7 +392,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine) array->arrayReserve(seqLength); for (quint32 ii = 0; ii < seqLength; ++ii) { value = deserialize(data, engine); - array->arrayData[ii].value = value; + array->arrayData[ii].value = value.asReturnedValue(); array->arrayDataLen = ii + 1; } array->setArrayLengthUnchecked(seqLength); diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h index 11b70ef..f552798 100644 --- a/src/qml/jsruntime/qv4value_def_p.h +++ b/src/qml/jsruntime/qv4value_def_p.h @@ -50,6 +50,18 @@ namespace QV4 { typedef uint Bool; +template +struct Returned : private T +{ + static Returned *create(T *t) { return static_cast *>(t); } + T *getPointer() { return this; } + template + static T *getPointer(Returned *x) { return x->getPointer(); } + template + Returned *as() { return Returned::create(Returned::getPointer(this)); } + using T::asReturnedValue; +}; + struct Q_QML_EXPORT Value { /* @@ -273,7 +285,6 @@ struct Q_QML_EXPORT Value return val; } - static Value fromObject(Object *o); static Value fromManaged(Managed *o); int toUInt16() const; @@ -349,9 +360,10 @@ struct SafeValue : public Value val = v.val; return *this; } - template - Returned *as(); + inline Returned *as(); + template + inline Referenced asRef(); }; struct Q_QML_EXPORT Primitive : public Value diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index e751a07..507c0f9 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -165,18 +165,6 @@ inline Primitive Primitive::fromUInt32(uint i) return v; } -inline Value Value::fromObject(Object *o) -{ - Value v; -#if QT_POINTER_SIZE == 8 - v.o = o; -#else - v.tag = Managed_Type; - v.o = o; -#endif - return v; -} - inline Value Value::fromManaged(Managed *m) { if (!m) diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index dfba6bb..ecc6287 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -1085,7 +1085,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // And, if the new value is a scarce resource, we need to ensure that it does not get // automatically released by the engine until no other references to it exist. QV4::ScopedValue newv(scope, QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value)); - if (QV4::VariantObject *v = newv->as()) + if (QV4::Referenced v = newv->asRef()) v->addVmePropertyReference(); // Write the value and emit change signal as appropriate. diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 066a266..3097031 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1560,7 +1560,7 @@ void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me) QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject); if (callingContext) { QV4::ScopedCallData callData(scope, 0); - callData->thisObject = activationObject.asValue(); + callData->thisObject = activationObject.asReturnedValue(); callback->call(callData); } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index b87ed63..bfce21f 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -3226,7 +3226,7 @@ public: if (!array) m->engine()->current->throwTypeError(); - if (name == m->engine()->id_length) { + if (name->isEqualTo(m->engine()->id_length)) { if (hasProperty) *hasProperty = true; return QV4::Encode(array->count()); diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index bab9a2c..6f7cd77 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -929,7 +929,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV8Engine* engi } QV4::Scoped imageData(scope, new (v4->memoryManager) QQuickJSContext2DImageData(v4)); - imageData->pixelData = pixelData.asValue(); + imageData->pixelData = pixelData.asReturnedValue(); return imageData.asReturnedValue(); } @@ -1386,7 +1386,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContex r->context->buffer()->setFillStyle(color); r->context->m_fillStyle = value; } else { - QQuickContext2DStyle *style = value->as(); + QV4::Scoped style(scope, value->as()); if (style && style->brush != r->context->state.fillStyle) { r->context->state.fillStyle = style->brush; r->context->buffer()->setFillStyle(style->brush, style->patternRepeatX, style->patternRepeatY); @@ -1501,7 +1501,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallCont r->context->buffer()->setStrokeStyle(color); r->context->m_strokeStyle = value; } else { - QQuickContext2DStyle *style = value->as(); + QV4::Scoped style(scope, value->as()); if (style && style->brush != r->context->state.strokeStyle) { r->context->state.strokeStyle = style->brush; r->context->buffer()->setStrokeStyle(style->brush, style->patternRepeatX, style->patternRepeatY); @@ -2099,7 +2099,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ct QV4::ScopedValue value(scope, ctx->argument(0)); r->context->beginPath(); - if (QV4::QObjectWrapper *qobjectWrapper =value->as()) { + if (QV4::Referenced qobjectWrapper = value->asRef()) { if (QQuickPath *path = qobject_cast(qobjectWrapper->object())) r->context->m_path = path->path(); } else { @@ -2964,7 +2964,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC pixmap = r->context->createPixmap(url); } else if (arg->isObject()) { - if (QV4::QObjectWrapper *qobjectWrapper = arg->as()) { + if (QV4::Referenced qobjectWrapper = arg->asRef()) { if (QQuickImage *imageItem = qobject_cast(qobjectWrapper->object())) { pixmap.take(r->context->createPixmap(imageItem->source())); } else if (QQuickCanvasItem *canvas = qobject_cast(qobjectWrapper->object())) { @@ -2974,7 +2974,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC } else { V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } - } else if (QQuickJSContext2DImageData *imageData = arg->as()) { + } else if (QV4::Referenced imageData = arg->asRef()) { QV4::Scoped pix(scope, imageData->pixelData.as()); if (pix && !pix->image.isNull()) { pixmap.take(new QQuickCanvasPixmap(pix->image, r->context->canvas()->window())); @@ -3239,7 +3239,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::Simpl if (ctx->callData->argc == 1) { QV4::ScopedValue arg0(scope, ctx->callData->args[0]); - if (QQuickJSContext2DImageData *imgData = arg0->as()) { + if (QV4::Referenced imgData = arg0->asRef()) { QV4::Scoped pa(scope, imgData->pixelData.as()); if (pa) { qreal w = pa->image.width(); @@ -3316,7 +3316,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::SimpleCa if (!qIsFinite(dx) || !qIsFinite(dy)) V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); - QQuickJSContext2DImageData *imageData = arg0->as(); + QV4::Referenced imageData = arg0->asRef(); if (!imageData) return ctx->callData->thisObject.asReturnedValue(); -- 2.7.4