diff options
Diffstat (limited to 'src/qml/jsruntime/qv4scopedvalue_p.h')
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 274 |
1 files changed, 234 insertions, 40 deletions
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index a0e0d784a7..a800283cee 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -79,61 +79,73 @@ struct ScopedValueArray { struct ScopedValue; -struct ValueScope { - ValueScope(ExecutionContext *ctx) +struct Scope { + Scope(ExecutionContext *ctx) : engine(ctx->engine) +#ifndef QT_NO_DEBUG + , size(0) +#endif { mark = ctx->engine->jsStackTop; } - ValueScope(ExecutionEngine *e) + Scope(ExecutionEngine *e) : engine(e) { mark = e->jsStackTop; } - ~ValueScope() { + ~Scope() { Q_ASSERT(engine->jsStackTop >= mark); engine->jsStackTop = mark; } ExecutionEngine *engine; Value *mark; +#ifndef QT_NO_DEBUG + mutable int size; +#endif }; struct ScopedValue; struct ValueRef; -struct ReturnedValue -{ - ReturnedValue(const Value &v) - : v(v) {} - // no destructor - - -private: - friend struct ValueRef; - friend struct ScopedValue; - QV4::Value v; -}; - struct ScopedValue { - ScopedValue(const ValueScope &scope) + ScopedValue(const Scope &scope) { ptr = scope.engine->jsStackTop++; +#ifndef QT_NO_DEBUG + ++scope.size; +#endif } - ScopedValue(const ValueScope &scope, const Value &v) + ScopedValue(const Scope &scope, const Value &v) { ptr = scope.engine->jsStackTop++; *ptr = v; +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + + ScopedValue(const Scope &scope, const ReturnedValue &v) + { + ptr = scope.engine->jsStackTop++; + ptr->val = v; +#ifndef QT_NO_DEBUG + ++scope.size; +#endif } - ScopedValue(const ValueScope &scope, const ReturnedValue &v) + template<typename T> + ScopedValue(const Scope &scope, Returned<T> *t) { ptr = scope.engine->jsStackTop++; - *ptr = v.v; + *ptr = t->getPointer() ? Value::fromManaged(t->getPointer()) : Value::undefinedValue(); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif } ScopedValue &operator=(const Value &v) { @@ -142,7 +154,13 @@ struct ScopedValue } ScopedValue &operator=(const ReturnedValue &v) { - *ptr = v.v; + ptr->val = v; + return *this; + } + + template<typename T> + ScopedValue &operator=(Returned<T> *t) { + *ptr = t->getPointer() ? Value::fromManaged(t->getPointer()) : Value::undefinedValue(); return *this; } @@ -155,32 +173,149 @@ struct ScopedValue return ptr; } + const Value *operator->() const { + return ptr; + } + operator const Value &() const { return *ptr; } + ReturnedValue asReturnedValue() const { return ptr->val; } + Value *ptr; }; -struct ScopedCallData { - ScopedCallData(ExecutionEngine *e, int argc) - : engine(e) - // ### this check currently won't work because of exceptions +template<typename T> +struct Scoped +{ + inline void setPointer(Managed *p) { +#if QT_POINTER_SIZE == 8 + ptr->val = (quint64)p; +#else + *ptr = p ? QV4::Value::fromManaged(p) : QV4::Value::undefinedValue(); +#endif + } + + Scoped(const Scope &scope) + { + ptr = scope.engine->jsStackTop++; #ifndef QT_NO_DEBUG - , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + ++scope.size; #endif + } + + // ### GC FIX casting below to be safe + Scoped(const Scope &scope, const Value &v) { - ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value))); - ptr->tag = 0; - ptr->argc = argc; + ptr = scope.engine->jsStackTop++; + setPointer(T::cast(v)); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif } - ~ScopedCallData() { + Scoped(const Scope &scope, const ValueRef &v); + + Scoped(const Scope &scope, T *t) + { + ptr = scope.engine->jsStackTop++; + setPointer(t); #ifndef QT_NO_DEBUG - engine->stackPop(size); - Q_ASSERT((void *)engine->jsStackTop == (void *)ptr); + ++scope.size; +#endif + } + template<typename X> + Scoped(const Scope &scope, Returned<X> *x) + { + ptr = scope.engine->jsStackTop++; + setPointer(Returned<T>::getPointer(x)); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + + Scoped(const Scope &scope, const ReturnedValue &v) + { + ptr = scope.engine->jsStackTop++; + setPointer(T::cast(QV4::Value::fromReturnedValue(v))); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + + Scoped<T> &operator=(const Value &v) { + setPointer(T::cast(v)); + return *this; + } + + Scoped<T> &operator=(const ValueRef &v); + + Scoped<T> &operator=(const ReturnedValue &v) { + setPointer(T::cast(QV4::Value::fromReturnedValue(v))); + return *this; + } + + Scoped<T> &operator=(const Scoped<T> &other) { + *ptr = *other.ptr; + return *this; + } + + Scoped<T> &operator=(T *t) { + setPointer(t); + return *this; + } + + template<typename X> + Scoped<T> &operator=(Returned<X> *x) { + setPointer(Returned<T>::getPointer(x)); + return *this; + } + + + T *operator->() { + return static_cast<T *>(ptr->managed()); + } + + bool operator!() const { + return !ptr->managed(); + } + operator bool() const { + return ptr->managed(); + } + + T *getPointer() { + return static_cast<T *>(ptr->managed()); + } + + Value asValue() const { +#if QT_POINTER_SIZE == 8 + return ptr->val ? *ptr : QV4::Value::undefinedValue(); +#else + return *ptr; +#endif + } + + ReturnedValue asReturnedValue() const { +#if QT_POINTER_SIZE == 8 + return ptr->val ? ptr->val : Value::undefinedValue().asReturnedValue(); #else - engine->jsStackTop = reinterpret_cast<Value *>(ptr); + return ptr->val; +#endif + } + + Value *ptr; +}; + +struct ScopedCallData { + ScopedCallData(Scope &scope, int argc) + { + int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value); + ptr = reinterpret_cast<CallData *>(scope.engine->stackPush(size)); + ptr->tag = QV4::Value::Integer_Type; + ptr->argc = argc; +#ifndef QT_NO_DEBUG + scope.size += size; #endif } @@ -192,17 +327,15 @@ struct ScopedCallData { return ptr; } - - ExecutionEngine *engine; -#ifndef QT_NO_DEBUG - int size; -#endif CallData *ptr; }; struct ValueRef { ValueRef(const ScopedValue &v) : ptr(v.ptr) {} + template <typename T> + ValueRef(const Scoped<T> &v) + : ptr(v.ptr) {} ValueRef(const PersistentValue &v) : ptr(&v.d->value) {} ValueRef(PersistentValuePrivate *p) @@ -218,7 +351,7 @@ struct ValueRef { ValueRef &operator=(const Value &v) { *ptr = v; return *this; } ValueRef &operator=(const ReturnedValue &v) { - *ptr = v.v; + ptr->val = v; return *this; } @@ -242,12 +375,32 @@ struct ValueRef { static const ValueRef fromRawValue(const Value *v) { return ValueRef(const_cast<Value *>(v)); } + + ReturnedValue asReturnedValue() const { return ptr->val; } + // ### get rid of this one! ValueRef(Value *v) { ptr = v; } private: Value *ptr; }; +template<typename T> +inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v) +{ + ptr = scope.engine->jsStackTop++; + setPointer(T::cast(*v.operator ->())); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif +} + +template<typename T> +inline Scoped<T> &Scoped<T>::operator=(const ValueRef &v) +{ + setPointer(T::cast(*v.operator ->())); + return *this; +} + struct CallDataRef { CallDataRef(const ScopedCallData &c) @@ -280,6 +433,47 @@ private: CallData *ptr; }; +struct Encode : private Value { + static ReturnedValue undefined() { + return quint64(Undefined_Type) << Tag_Shift; + } + static ReturnedValue null() { + return quint64(_Null_Type) << Tag_Shift; + } + + Encode(bool b) { + tag = _Boolean_Type; + int_32 = b; + } + Encode(double d) { + setDouble(d); + } + Encode(int i) { + tag = _Integer_Type; + int_32 = i; + } + Encode(uint i) { + if (i <= INT_MAX) { + tag = _Integer_Type; + int_32 = i; + } else { + setDouble(i); + } + } + Encode(ReturnedValue v) { + val = v; + } + + template<typename T> + Encode(Returned<T> *t) { + val = t->getPointer()->asReturnedValue(); + } + + operator ReturnedValue() const { + return val; + } +}; + } QT_END_NAMESPACE |