/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJS_MANAGED_H #define QMLJS_MANAGED_H #include #include #include #include "qv4global_p.h" #include "qv4value_def_p.h" QT_BEGIN_NAMESPACE namespace QV4 { #define Q_MANAGED_CHECK \ template inline void qt_check_for_QMANAGED_macro(const T &_q_argument) const \ { int i = qYouForgotTheQ_MANAGED_Macro(this, &_q_argument); i = i + 1; } template inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; } template inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} #define Q_MANAGED \ public: \ Q_MANAGED_CHECK \ static const QV4::ManagedVTable static_vtbl; \ template \ QV4::Returned *asReturned() { return QV4::Returned::create(this); } \ struct GCDeletable { GCDeletable() : next(0), lastCall(false) {} virtual ~GCDeletable() {} GCDeletable *next; bool lastCall; }; struct ManagedVTable { ReturnedValue (*call)(Managed *, CallData *data); ReturnedValue (*construct)(Managed *, CallData *data); void (*markObjects)(Managed *, ExecutionEngine *e); void (*destroy)(Managed *); void (*collectDeletables)(Managed *, GCDeletable **deletable); bool (*hasInstance)(Managed *, const ValueRef value); ReturnedValue (*get)(Managed *, const StringRef name, bool *hasProperty); ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty); void (*put)(Managed *, const StringRef name, const ValueRef value); void (*putIndexed)(Managed *, uint index, const ValueRef value); PropertyAttributes (*query)(const Managed *, StringRef name); PropertyAttributes (*queryIndexed)(const Managed *, uint index); bool (*deleteProperty)(Managed *m, const StringRef name); bool (*deleteIndexedProperty)(Managed *m, uint index); ReturnedValue (*getLookup)(Managed *m, Lookup *l); void (*setLookup)(Managed *m, Lookup *l, const ValueRef v); bool (*isEqualTo)(Managed *m, Managed *other); Property *(*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes); const char *className; }; #define DEFINE_MANAGED_VTABLE(classname) \ const QV4::ManagedVTable classname::static_vtbl = \ { \ call, \ construct, \ markObjects, \ destroy, \ 0, \ hasInstance, \ get, \ getIndexed, \ put, \ putIndexed, \ query, \ queryIndexed, \ deleteProperty, \ deleteIndexedProperty, \ getLookup, \ setLookup, \ isEqualTo, \ advanceIterator, \ #classname \ } #define DEFINE_MANAGED_VTABLE_WITH_DELETABLES(classname) \ const QV4::ManagedVTable classname::static_vtbl = \ { \ call, \ construct, \ markObjects, \ destroy, \ collectDeletables, \ hasInstance, \ get, \ getIndexed, \ put, \ putIndexed, \ query, \ queryIndexed, \ deleteProperty, \ deleteIndexedProperty, \ getLookup, \ setLookup, \ isEqualTo, \ advanceIterator, \ #classname \ } struct Q_QML_EXPORT Managed { Q_MANAGED private: void *operator new(size_t); Managed(const Managed &other); void operator = (const Managed &other); protected: Managed(InternalClass *internal) : _data(0), vtbl(&static_vtbl), internalClass(internal) { inUse = 1; extensible = 1; } public: void *operator new(size_t size, MemoryManager *mm); void operator delete(void *ptr); void operator delete(void *ptr, MemoryManager *mm); inline void mark(QV4::ExecutionEngine *engine); enum Type { Type_Invalid, Type_String, Type_Object, Type_ArrayObject, Type_FunctionObject, Type_BooleanObject, Type_NumberObject, Type_StringObject, Type_DateObject, Type_RegExpObject, Type_ErrorObject, Type_ArgumentsObject, Type_JSONObject, Type_MathObject, Type_ForeachIteratorObject, Type_RegExp, Type_QmlSequence }; ExecutionEngine *engine() const; template T *as() { // ### FIXME: if (!this) return 0; #if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast(this)); #endif return vtbl == &T::static_vtbl ? static_cast(this) : 0; } template const T *as() const { // ### FIXME: if (!this) return 0; #if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast(const_cast(this))); #endif return vtbl == &T::static_vtbl ? static_cast(this) : 0; } String *asString() { return type == Type_String ? reinterpret_cast(this) : 0; } Object *asObject() { return type != Type_String ? reinterpret_cast(this) : 0; } ArrayObject *asArrayObject() { return type == Type_ArrayObject ? reinterpret_cast(this) : 0; } FunctionObject *asFunctionObject() { return type == Type_FunctionObject ? reinterpret_cast(this) : 0; } BooleanObject *asBooleanObject() { return type == Type_BooleanObject ? reinterpret_cast(this) : 0; } NumberObject *asNumberObject() { return type == Type_NumberObject ? reinterpret_cast(this) : 0; } StringObject *asStringObject() { return type == Type_StringObject ? reinterpret_cast(this) : 0; } DateObject *asDateObject() { return type == Type_DateObject ? reinterpret_cast(this) : 0; } ErrorObject *asErrorObject() { return type == Type_ErrorObject ? reinterpret_cast(this) : 0; } ArgumentsObject *asArgumentsObject() { return type == Type_ArgumentsObject ? reinterpret_cast(this) : 0; } bool isListType() const { return type == Type_QmlSequence; } bool isArrayObject() const { return type == Type_ArrayObject; } bool isStringObject() const { return type == Type_StringObject; } QString className() const; Managed **nextFreeRef() { return reinterpret_cast(this); } Managed *nextFree() { return *reinterpret_cast(this); } void setNextFree(Managed *m) { *reinterpret_cast(this) = m; } bool hasInstance(const ValueRef v); ReturnedValue construct(CallData *d); ReturnedValue call(CallData *d); ReturnedValue get(const StringRef name, bool *hasProperty = 0); ReturnedValue getIndexed(uint index, bool *hasProperty = 0); void put(const StringRef name, const ValueRef value); void putIndexed(uint index, const ValueRef value); PropertyAttributes query(StringRef name) const; PropertyAttributes queryIndexed(uint index) const { return vtbl->queryIndexed(this, index); } bool deleteProperty(const StringRef name); bool deleteIndexedProperty(uint index) { return vtbl->deleteIndexedProperty(this, index); } ReturnedValue getLookup(Lookup *l) { return vtbl->getLookup(this, l); } void setLookup(Lookup *l, const ValueRef v); bool isEqualTo(Managed *other) { return vtbl->isEqualTo(this, other); } Property *advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes); static void destroy(Managed *that) { that->_data = 0; } static bool hasInstance(Managed *that, const ValueRef value); static ReturnedValue construct(Managed *m, CallData *d); static ReturnedValue call(Managed *m, CallData *); static ReturnedValue getLookup(Managed *m, Lookup *); static void setLookup(Managed *m, Lookup *l, const ValueRef v); static bool isEqualTo(Managed *m, Managed *other); uint internalType() const { return type; } ReturnedValue asReturnedValue() { return Value::fromManaged(this).asReturnedValue(); } enum { SimpleArray = 1 }; union { uint _data; struct { uchar markBit : 1; uchar inUse : 1; uchar extensible : 1; // used by Object uchar isNonStrictArgumentsObject : 1; uchar needsActivation : 1; // used by FunctionObject uchar strictMode : 1; // used by FunctionObject uchar bindingKeyFlag : 1; uchar hasAccessorProperty : 1; uchar type; mutable uchar subtype; uchar flags; }; }; protected: const ManagedVTable *vtbl; public: InternalClass *internalClass; private: friend class MemoryManager; friend struct Identifiers; friend struct ObjectIterator; }; template<> inline Managed *value_cast(const Value &v) { return v.asManaged(); } template inline T *managed_cast(Managed *m) { return m->as(); } template<> inline String *managed_cast(Managed *m) { return m->asString(); } template<> inline Object *managed_cast(Managed *m) { return m->asObject(); } template<> inline FunctionObject *managed_cast(Managed *m) { return m->asFunctionObject(); } inline ReturnedValue Managed::construct(CallData *d) { return vtbl->construct(this, d); } inline ReturnedValue Managed::call(CallData *d) { return vtbl->call(this, d); } } QT_END_NAMESPACE #endif