Move the vtable pointer from the object to the internal class
authorLars Knoll <lars.knoll@digia.com>
Thu, 21 Nov 2013 12:15:46 +0000 (13:15 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 4 Dec 2013 08:45:45 +0000 (09:45 +0100)
This saves one pointer per object, and willmake other optimizations
easier in the future.

Change-Id: I1324cad31998896b5dc76af3c8a7ee9d86283bfe
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
53 files changed:
src/imports/localstorage/plugin.cpp
src/particles/qquickv4particledata.cpp
src/qml/debugger/qv4debugservice.cpp
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4argumentsobject_p.h
src/qml/jsruntime/qv4arrayobject.cpp
src/qml/jsruntime/qv4booleanobject.cpp
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4dateobject.cpp
src/qml/jsruntime/qv4dateobject_p.h
src/qml/jsruntime/qv4debugging.cpp
src/qml/jsruntime/qv4debugging_p.h
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4errorobject.cpp
src/qml/jsruntime/qv4errorobject_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4global_p.h
src/qml/jsruntime/qv4globalobject.cpp
src/qml/jsruntime/qv4internalclass.cpp
src/qml/jsruntime/qv4internalclass_p.h
src/qml/jsruntime/qv4managed.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4mm.cpp
src/qml/jsruntime/qv4numberobject.cpp
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4objectiterator_p.h
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4regexp.cpp
src/qml/jsruntime/qv4regexpobject.cpp
src/qml/jsruntime/qv4scopedvalue_p.h
src/qml/jsruntime/qv4script.cpp
src/qml/jsruntime/qv4sequenceobject.cpp
src/qml/jsruntime/qv4string.cpp
src/qml/jsruntime/qv4string_p.h
src/qml/jsruntime/qv4stringobject.cpp
src/qml/jsruntime/qv4variantobject.cpp
src/qml/qml/qqmlcomponent.cpp
src/qml/qml/qqmlcontextwrapper.cpp
src/qml/qml/qqmllistwrapper.cpp
src/qml/qml/qqmllocale.cpp
src/qml/qml/qqmltypewrapper.cpp
src/qml/qml/qqmlvaluetypewrapper.cpp
src/qml/qml/qqmlxmlhttprequest.cpp
src/qml/qml/v8/qqmlbuiltinfunctions.cpp
src/qml/types/qqmldelegatemodel.cpp
src/qml/types/qqmldelegatemodel_p_p.h
src/quick/items/context2d/qquickcontext2d.cpp
tools/qmljs/main.cpp

index 145487c..1dbf0d5 100644 (file)
@@ -108,7 +108,7 @@ public:
     QQmlSqlDatabaseWrapper(QV8Engine *e)
         : Object(QV8Engine::getV4(e)), type(Database), inTransaction(false), readonly(false), forwardOnly(false)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
 
     ~QQmlSqlDatabaseWrapper() {
index 6f9cd82..d0e9a39 100644 (file)
@@ -277,7 +277,7 @@ struct QV4ParticleData : public QV4::Object
     QV4ParticleData(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
         : Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         this->datum = datum;
     }
 
index 400bb18..1bf38dc 100644 (file)
@@ -432,7 +432,7 @@ public:
 
         QJsonArray scopes;
         // Only type and index are used by Qt Creator, so we keep it easy:
-        QVector<QV4::ExecutionContext::Type> scopeTypes = debugger->getScopeTypes(frameNr);
+        QVector<QV4::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
         for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
             int type = encodeScopeType(scopeTypes[i]);
             if (type == -1)
@@ -448,7 +448,7 @@ public:
         return frame;
     }
 
-    int encodeScopeType(QV4::ExecutionContext::Type scopeType)
+    int encodeScopeType(QV4::ExecutionContext::ContextType scopeType)
     {
         switch (scopeType) {
         case QV4::ExecutionContext::Type_GlobalContext:
@@ -480,7 +480,7 @@ public:
         QJsonObject anonymous;
         anonymous[QLatin1String("properties")] = properties;
 
-        QVector<QV4::ExecutionContext::Type> scopeTypes = debugger->getScopeTypes(frameNr);
+        QVector<QV4::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
         scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
         scope[QLatin1String("index")] = scopeNr;
         scope[QLatin1String("frameIndex")] = frameNr;
index 749509c..0fd0242 100644 (file)
@@ -47,9 +47,10 @@ using namespace QV4;
 DEFINE_MANAGED_VTABLE(ArgumentsObject);
 
 ArgumentsObject::ArgumentsObject(CallContext *context)
-    : Object(context->engine), context(context), fullyCreated(false)
+    : Object(context->strictMode ? context->engine->strictArgumentsObjectClass : context->engine->argumentsObjectClass)
+    , context(context)
+    , fullyCreated(false)
 {
-    vtbl = &static_vtbl;
     type = Type_ArgumentsObject;
     flags &= ~SimpleArray;
 
@@ -58,8 +59,6 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
     ScopedObject protectThis(scope, this);
 
     if (context->strictMode) {
-        internalClass = v4->strictArgumentsObjectClass;
-
         Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
         Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
         Q_ASSERT(CallerPropertyIndex == internalClass->find(context->engine->id_caller));
@@ -72,7 +71,6 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
         arrayDataLen = context->callData->argc;
         fullyCreated = true;
     } else {
-        internalClass = engine()->argumentsObjectClass;
         Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
         memberData[CalleePropertyIndex].value = context->function->asReturnedValue();
         isNonStrictArgumentsObject = true;
@@ -80,6 +78,8 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
     Q_ASSERT(LengthPropertyIndex == internalClass->find(context->engine->id_length));
     Property *lp = memberData + ArrayObject::LengthPropertyIndex;
     lp->value = Primitive::fromInt32(context->realArgumentCount);
+
+    setVTable(&static_vtbl);
 }
 
 void ArgumentsObject::destroy(Managed *that)
index 7c58c48..d306fae 100644 (file)
@@ -54,7 +54,9 @@ struct ArgumentsGetterFunction: FunctionObject
     uint index;
 
     ArgumentsGetterFunction(ExecutionContext *scope, uint index)
-        : FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
+        : FunctionObject(scope), index(index) {
+        setVTable(&static_vtbl);
+    }
 
     static ReturnedValue call(Managed *that, CallData *d);
 };
@@ -65,7 +67,9 @@ struct ArgumentsSetterFunction: FunctionObject
     uint index;
 
     ArgumentsSetterFunction(ExecutionContext *scope, uint index)
-        : FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
+        : FunctionObject(scope), index(index) {
+        setVTable(&static_vtbl);
+    }
 
     static ReturnedValue call(Managed *that, CallData *callData);
 };
index a0f0345..39b9b9e 100644 (file)
@@ -51,7 +51,7 @@ DEFINE_MANAGED_VTABLE(ArrayCtor);
 ArrayCtor::ArrayCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Array"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
index a0d0027..f8edfb7 100644 (file)
@@ -49,7 +49,7 @@ DEFINE_MANAGED_VTABLE(BooleanObject);
 BooleanCtor::BooleanCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Boolean"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
index aea7827..f9b63ac 100644 (file)
@@ -76,12 +76,10 @@ const ManagedVTable ExecutionContext::static_vtbl =
 CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
 {
     CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc)));
-    c->init();
+    new (c) CallContext(engine, this, Type_CallContext);
 
     engine->current = c;
 
-    c->initBaseContext(Type_CallContext, engine, this);
-
     c->function = function;
     c->realArgumentCount = callData->argc;
 
@@ -114,28 +112,22 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData
 
 WithContext *ExecutionContext::newWithContext(ObjectRef with)
 {
-    WithContext *w = new (engine->memoryManager) WithContext;
+    WithContext *w = new (engine->memoryManager) WithContext(this, with);
     engine->current = w;
-    w->initWithContext(this, with);
     return w;
 }
 
 CatchContext *ExecutionContext::newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue)
 {
-    CatchContext *c = new (engine->memoryManager) CatchContext;
+    CatchContext *c = new (engine->memoryManager) CatchContext(this, exceptionVarName, exceptionValue);
     engine->current = c;
-    c->initCatchContext(this, exceptionVarName, exceptionValue);
     return c;
 }
 
 CallContext *ExecutionContext::newQmlContext(FunctionObject *f, ObjectRef qml)
 {
     CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0)));
-    c->init();
-
-    engine->current = c;
-    c->initQmlContext(this, qml, f);
-
+    new (c) CallContext(this, qml, f);
     return c;
 }
 
@@ -200,20 +192,22 @@ unsigned int ExecutionContext::variableCount() const
 }
 
 
-void GlobalContext::initGlobalContext(ExecutionEngine *eng)
+GlobalContext::GlobalContext(ExecutionEngine *eng, ExecutionContext *parent)
+    : ExecutionContext(eng, Type_GlobalContext, parent)
 {
-    initBaseContext(Type_GlobalContext, eng, /*parentContext*/0);
-    callData = reinterpret_cast<CallData *>(this + 1);
-    callData->tag = QV4::Value::_Integer_Type;
-    callData->argc = 0;
-    callData->thisObject = eng->globalObject;
-    callData->args[0] = Encode::undefined();
+    if (!parent) {
+        callData = reinterpret_cast<CallData *>(this + 1);
+        callData->tag = QV4::Value::_Integer_Type;
+        callData->argc = 0;
+        callData->thisObject = eng->globalObject;
+        callData->args[0] = Encode::undefined();
+    }
     global = 0;
 }
 
-void WithContext::initWithContext(ExecutionContext *p, ObjectRef with)
+WithContext::WithContext(ExecutionContext *p, ObjectRef with)
+    : ExecutionContext(p->engine, Type_WithContext, p)
 {
-    initBaseContext(Type_WithContext, p->engine, p);
     callData = p->callData;
     outer = p;
     lookups = p->lookups;
@@ -222,9 +216,9 @@ void WithContext::initWithContext(ExecutionContext *p, ObjectRef with)
     withObject = with.getPointer();
 }
 
-void CatchContext::initCatchContext(ExecutionContext *p, const StringRef exceptionVarName, const ValueRef exceptionValue)
+CatchContext::CatchContext(ExecutionContext *p, const StringRef exceptionVarName, const ValueRef exceptionValue)
+    : ExecutionContext(p->engine, Type_CatchContext, p)
 {
-    initBaseContext(Type_CatchContext, p->engine, p);
     strictMode = p->strictMode;
     callData = p->callData;
     outer = p;
@@ -235,18 +229,17 @@ void CatchContext::initCatchContext(ExecutionContext *p, const StringRef excepti
     this->exceptionValue = exceptionValue;
 }
 
-void CallContext::initQmlContext(ExecutionContext *parentContext, ObjectRef qml, FunctionObject *function)
+CallContext::CallContext(ExecutionContext *parentContext, ObjectRef qml, FunctionObject *function)
+    : ExecutionContext(parentContext->engine, Type_QmlContext, parentContext)
 {
-    initBaseContext(Type_QmlContext, parentContext->engine, parentContext);
-
     this->function = function;
-    this->callData = reinterpret_cast<CallData *>(this + 1);
-    this->callData->tag = QV4::Value::_Integer_Type;
-    this->callData->argc = 0;
-    this->callData->thisObject = Primitive::undefinedValue();
+    callData = reinterpret_cast<CallData *>(this + 1);
+    callData->tag = QV4::Value::_Integer_Type;
+    callData->argc = 0;
+    callData->thisObject = Primitive::undefinedValue();
 
     strictMode = true;
-    this->outer = function->scope;
+    outer = function->scope;
 #ifndef QT_NO_DEBUG
     assert(outer->next != (ExecutionContext *)0x1);
 #endif
index c06c104..2cdcf2b 100644 (file)
@@ -44,6 +44,7 @@
 #include "qv4global_p.h"
 #include "qv4value_def_p.h"
 #include "qv4managed_p.h"
+#include "qv4engine_p.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -69,19 +70,8 @@ struct WithContext;
 struct Q_QML_EXPORT ExecutionContext : public Managed
 {
     Q_MANAGED
-    ExecutionContext()
-        : Managed(0) {
-        vtbl = &static_vtbl;
-    }
-    void init() {
-        _data = 0;
-        internalClass = 0;
-        inUse = 1;
-        extensible = 1;
-        vtbl = &static_vtbl;
-    }
 
-    enum Type {
+    enum ContextType {
         Type_GlobalContext = 0x1,
         Type_CatchContext = 0x2,
         Type_WithContext = 0x3,
@@ -90,7 +80,23 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
         Type_QmlContext = 0x6
     };
 
-    Type type;
+    ExecutionContext(ExecutionEngine *engine, ContextType t, ExecutionContext *parent)
+        : Managed(engine->emptyClass)
+    {
+        setVTable(&static_vtbl);
+        this->type = t;
+        strictMode = false;
+        this->engine = engine;
+        this->parent = parent;
+        outer = 0;
+        lookups = 0;
+        compilationUnit = 0;
+        currentEvalCode = 0;
+        interpreterInstructionPointer = 0;
+        lineNumber = -1;
+    }
+
+    ContextType type;
     bool strictMode;
 
     CallData *callData;
@@ -112,20 +118,6 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
     const uchar **interpreterInstructionPointer;
     int lineNumber;
 
-    void initBaseContext(Type type, ExecutionEngine *engine, ExecutionContext *parentContext)
-    {
-        this->type = type;
-        strictMode = false;
-        this->engine = engine;
-        parent = parentContext;
-        outer = 0;
-        lookups = 0;
-        compilationUnit = 0;
-        currentEvalCode = 0;
-        interpreterInstructionPointer = 0;
-        lineNumber = -1;
-    }
-
     CallContext *newCallContext(FunctionObject *f, CallData *callData);
     WithContext *newWithContext(ObjectRef with);
     CatchContext *newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue);
@@ -168,17 +160,20 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
 
 struct CallContext : public ExecutionContext
 {
+    CallContext(ExecutionEngine *engine, ExecutionContext *parent, ContextType t = Type_SimpleCallContext)
+        : ExecutionContext(engine, t, parent)
+    {
+        function = 0;
+        locals = 0;
+        activation = 0;
+    }
+    CallContext(ExecutionContext *parentContext, ObjectRef qml, QV4::FunctionObject *function);
+
     FunctionObject *function;
     int realArgumentCount;
     SafeValue *locals;
     Object *activation;
 
-    void initSimpleCallContext(ExecutionEngine *engine, ExecutionContext *parent) {
-        initBaseContext(Type_SimpleCallContext, engine, parent);
-        function = 0;
-        locals = 0;
-        activation = 0;
-    }
     void initQmlContext(ExecutionContext *parentContext, ObjectRef qml, QV4::FunctionObject *function);
 
     inline ReturnedValue argument(int i);
@@ -187,14 +182,14 @@ struct CallContext : public ExecutionContext
 
 struct GlobalContext : public ExecutionContext
 {
-    void initGlobalContext(ExecutionEngine *e);
+    GlobalContext(ExecutionEngine *engine, ExecutionContext *parent = 0);
 
     Object *global;
 };
 
 struct CatchContext : public ExecutionContext
 {
-    void initCatchContext(ExecutionContext *p, const StringRef exceptionVarName, const ValueRef exceptionValue);
+    CatchContext(ExecutionContext *p, const StringRef exceptionVarName, const ValueRef exceptionValue);
 
     SafeString exceptionVarName;
     SafeValue exceptionValue;
@@ -202,9 +197,8 @@ struct CatchContext : public ExecutionContext
 
 struct WithContext : public ExecutionContext
 {
+    WithContext(ExecutionContext *p, ObjectRef with);
     Object *withObject;
-
-    void initWithContext(ExecutionContext *p, ObjectRef with);
 };
 
 inline CallContext *ExecutionContext::asCallContext()
@@ -217,6 +211,36 @@ inline const CallContext *ExecutionContext::asCallContext() const
     return type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
 }
 
+
+inline void ExecutionEngine::pushContext(CallContext *context)
+{
+    context->parent = current;
+    current = context;
+    current->currentEvalCode = 0;
+}
+
+inline ExecutionContext *ExecutionEngine::popContext()
+{
+    current = current->parent;
+    return current;
+}
+
+struct ExecutionContextSaver
+{
+    ExecutionEngine *engine;
+    ExecutionContext *savedContext;
+
+    ExecutionContextSaver(ExecutionContext *context)
+        : engine(context->engine)
+        , savedContext(context)
+    {
+    }
+    ~ExecutionContextSaver()
+    {
+        engine->current = savedContext;
+    }
+};
+
 /* Function *f, int argc */
 #define requiredMemoryForExecutionContect(f, argc) \
     sizeof(CallContext) + sizeof(Value) * (f->varCount + qMax((uint)argc, f->formalParameterCount)) + sizeof(CallData)
index b732c8a..5d0c8cc 100644 (file)
@@ -646,7 +646,7 @@ DEFINE_MANAGED_VTABLE(DateObject);
 DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date)
     : Object(engine->dateClass)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     type = Type_DateObject;
     value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
 }
@@ -661,7 +661,7 @@ DEFINE_MANAGED_VTABLE(DateCtor);
 DateCtor::DateCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Date"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
index e96cac2..f74037a 100644 (file)
@@ -55,7 +55,7 @@ struct DateObject: Object {
     Q_MANAGED
     SafeValue value;
     DateObject(ExecutionEngine *engine, const ValueRef date): Object(engine->dateClass) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_DateObject;
         value = date;
     }
@@ -65,7 +65,7 @@ struct DateObject: Object {
 
 protected:
     DateObject(InternalClass *ic): Object(ic) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_DateObject;
         value = Primitive::fromDouble(qSNaN());
     }
index 1673428..e14ea25 100644 (file)
@@ -449,9 +449,9 @@ void Debugger::collectReturnedValue(Collector *collector) const
     collector->collect(o);
 }
 
-QVector<ExecutionContext::Type> Debugger::getScopeTypes(int frame) const
+QVector<ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
 {
-    QVector<ExecutionContext::Type> types;
+    QVector<ExecutionContext::ContextType> types;
 
     if (state() != Paused)
         return types;
index 98b5499..0e19c51 100644 (file)
@@ -163,7 +163,7 @@ public:
     bool collectThisInContext(Collector *collector, int frame = 0);
     void collectThrownValue(Collector *collector);
     void collectReturnedValue(Collector *collector) const;
-    QVector<ExecutionContext::Type> getScopeTypes(int frame = 0) const;
+    QVector<ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
 
 public: // compile-time interface
     void maybeBreakAtInstruction(const uchar *code, bool breakPointHit);
index 50db0e0..b50d4d8 100644 (file)
@@ -39,6 +39,7 @@
 **
 ****************************************************************************/
 #include <qv4engine_p.h>
+#include <qv4context_p.h>
 #include <qv4value_p.h>
 #include <qv4object_p.h>
 #include <qv4objectproto_p.h>
@@ -215,16 +216,22 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     id_valueOf = newIdentifier(QStringLiteral("valueOf"));
 
     ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(emptyClass);
-    objectClass = emptyClass->changePrototype(objectPrototype);
+    objectClass = emptyClass->changeVTable(&Object::static_vtbl);
+    objectClass = objectClass->changePrototype(objectPrototype);
+    Q_ASSERT(objectClass->vtable == &Object::static_vtbl);
 
     arrayClass = objectClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
     ArrayPrototype *arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass);
     arrayClass = arrayClass->changePrototype(arrayPrototype);
 
-    InternalClass *argsClass = objectClass->addMember(id_length, Attr_NotEnumerable);
+    InternalClass *argsClass = objectClass->changeVTable(&ArgumentsObject::static_vtbl);
+    argsClass = argsClass->addMember(id_length, Attr_NotEnumerable);
     argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
     strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
     strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+    Q_ASSERT(argumentsObjectClass->vtable == &ArgumentsObject::static_vtbl);
+    Q_ASSERT(strictArgumentsObjectClass->vtable == &ArgumentsObject::static_vtbl);
+
     initRootContext();
 
     StringPrototype *stringPrototype = new (memoryManager) StringPrototype(objectClass);
@@ -391,10 +398,9 @@ void ExecutionEngine::enableDebugger()
 void ExecutionEngine::initRootContext()
 {
     rootContext = static_cast<GlobalContext *>(memoryManager->allocManaged(sizeof(GlobalContext) + sizeof(CallData)));
-    rootContext->init();
+    new (rootContext) GlobalContext(this);
     current = rootContext;
     current->parent = 0;
-    rootContext->initGlobalContext(this);
 }
 
 InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -404,11 +410,10 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
 
 ExecutionContext *ExecutionEngine::pushGlobalContext()
 {
-    GlobalContext *g = new (memoryManager) GlobalContext;
+    GlobalContext *g = new (memoryManager) GlobalContext(this, current);
     ExecutionContext *oldNext = g->next;
     memcpy(g, rootContext, sizeof(GlobalContext));
     g->next = oldNext;
-    g->parent = current;
     current = g;
 
     return current;
index c37d4f1..77378fb 100644 (file)
@@ -44,7 +44,6 @@
 #include "qv4global_p.h"
 #include "private/qv4isel_p.h"
 #include "qv4util_p.h"
-#include "qv4context_p.h"
 #include "qv4property_p.h"
 #include <private/qintrusivelist_p.h>
 
@@ -356,35 +355,6 @@ private:
     QmlExtensions *m_qmlExtensions;
 };
 
-inline void ExecutionEngine::pushContext(CallContext *context)
-{
-    context->parent = current;
-    current = context;
-    current->currentEvalCode = 0;
-}
-
-inline ExecutionContext *ExecutionEngine::popContext()
-{
-    current = current->parent;
-    return current;
-}
-
-struct ExecutionContextSaver
-{
-    ExecutionEngine *engine;
-    ExecutionContext *savedContext;
-
-    ExecutionContextSaver(ExecutionContext *context)
-        : engine(context->engine)
-        , savedContext(context)
-    {
-    }
-    ~ExecutionContextSaver()
-    {
-        engine->current = savedContext;
-    }
-};
-
 inline
 void Managed::mark(QV4::ExecutionEngine *engine)
 {
index bac29d1..d5b4975 100644 (file)
@@ -77,7 +77,7 @@ ErrorObject::ErrorObject(InternalClass *ic)
     , stack(0)
 {
     type = Type_ErrorObject;
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 
     Scope scope(engine());
     ScopedValue protectThis(scope, this);
@@ -91,7 +91,7 @@ ErrorObject::ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t)
     , stack(0)
 {
     type = Type_ErrorObject;
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     subtype = t;
 
     Scope scope(engine());
@@ -116,7 +116,7 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, ErrorObject:
     , stack(0)
 {
     type = Type_ErrorObject;
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     subtype = t;
 
     Scope scope(engine());
@@ -141,7 +141,7 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QStrin
     , stack(0)
 {
     type = Type_ErrorObject;
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     subtype = t;
 
     Scope scope(engine());
@@ -207,13 +207,13 @@ DEFINE_MANAGED_VTABLE(SyntaxErrorObject);
 SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg)
     : ErrorObject(engine->syntaxErrorClass, msg, SyntaxError)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
     : ErrorObject(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const ValueRef message)
@@ -272,13 +272,13 @@ DEFINE_MANAGED_VTABLE(URIErrorCtor);
 ErrorCtor::ErrorCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Error"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ErrorCtor::ErrorCtor(ExecutionContext *scope, const QString &name)
     : FunctionObject(scope, name)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
@@ -296,7 +296,7 @@ ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
 EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
     : ErrorCtor(scope, QStringLiteral("EvalError"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
@@ -309,7 +309,7 @@ ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
 RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
     : ErrorCtor(scope, QStringLiteral("RangeError"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
@@ -322,7 +322,7 @@ ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
 ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
     : ErrorCtor(scope, QStringLiteral("ReferenceError"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
@@ -335,7 +335,7 @@ ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
 SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
     : ErrorCtor(scope, QStringLiteral("SyntaxError"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
@@ -348,7 +348,7 @@ ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
 TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
     : ErrorCtor(scope, QStringLiteral("TypeError"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
@@ -361,7 +361,7 @@ ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
 URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
     : ErrorCtor(scope, QStringLiteral("URIError"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
index 3f4cb8f..def776d 100644 (file)
@@ -184,37 +184,37 @@ struct ErrorPrototype: ErrorObject
 
 struct EvalErrorPrototype: ErrorObject
 {
-    EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
+    EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
     void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
 struct RangeErrorPrototype: ErrorObject
 {
-    RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
+    RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
     void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
 struct ReferenceErrorPrototype: ErrorObject
 {
-    ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
+    ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
     void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
 struct SyntaxErrorPrototype: ErrorObject
 {
-    SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
+    SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
     void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
 struct TypeErrorPrototype: ErrorObject
 {
-    TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
+    TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
     void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
 struct URIErrorPrototype: ErrorObject
 {
-    URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
+    URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(&static_vtbl); }
     void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
index b9859d2..6ca1187 100644 (file)
@@ -110,7 +110,7 @@ FunctionObject::FunctionObject(InternalClass *ic)
     , varCount(0)
     , function(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     name = ic->engine->id_undefined;
 
     type = Type_FunctionObject;
@@ -126,7 +126,7 @@ FunctionObject::~FunctionObject()
 
 void FunctionObject::init(const StringRef n, bool createProto)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     name = n;
 
     Scope s(internalClass->engine);
@@ -221,7 +221,7 @@ DEFINE_MANAGED_VTABLE(FunctionCtor);
 FunctionCtor::FunctionCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Function"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 // 15.3.2
@@ -386,7 +386,7 @@ DEFINE_MANAGED_VTABLE(ScriptFunction);
 ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
     : FunctionObject(scope, function->name, true)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 
     Scope s(scope);
     ScopedValue protectThis(s, this);
@@ -471,7 +471,7 @@ DEFINE_MANAGED_VTABLE(SimpleScriptFunction);
 SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *function)
     : FunctionObject(scope, function->name, true)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 
     Scope s(scope);
     ScopedValue protectThis(s, this);
@@ -519,8 +519,7 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
 
     ExecutionContext *context = v4->current;
 
-    CallContext ctx;
-    ctx.initSimpleCallContext(v4, context);
+    CallContext ctx(v4, context);
     ctx.strictMode = f->strictMode;
     ctx.callData = callData;
     ctx.function = f.getPointer();
@@ -557,8 +556,7 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
     Scope scope(v4);
     ExecutionContext *context = v4->current;
 
-    CallContext ctx;
-    ctx.initSimpleCallContext(v4, context);
+    CallContext ctx(v4, context);
     ctx.strictMode = f->strictMode;
     ctx.callData = callData;
     ctx.function = f;
@@ -588,7 +586,7 @@ BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name,
     : FunctionObject(scope, name)
     , code(code)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
@@ -606,8 +604,7 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
 
     ExecutionContext *context = v4->current;
 
-    CallContext ctx;
-    ctx.initSimpleCallContext(v4, context);
+    CallContext ctx(v4, context);
     ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
     ctx.callData = callData;
     v4->pushContext(&ctx);
@@ -625,10 +622,8 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
     CHECK_STACK_LIMITS(v4);
 
     ExecutionContext *context = v4->current;
-    Scope scope(v4);
 
-    CallContext ctx;
-    ctx.initSimpleCallContext(v4, context);
+    CallContext ctx(v4, context);
     ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
     ctx.callData = callData;
     v4->pushContext(&ctx);
@@ -646,7 +641,7 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target,
     , target(target)
     , boundArgs(boundArgs)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     subtype = FunctionObject::BoundFunction;
     this->boundThis = boundThis;
 
index 9909893..2e1f1d1 100644 (file)
@@ -125,10 +125,10 @@ struct Q_QML_EXPORT FunctionObject: Object {
     static ReturnedValue construct(Managed *that, CallData *);
     static ReturnedValue call(Managed *that, CallData *d);
     inline ReturnedValue construct(CallData *callData) {
-        return vtbl->construct(this, callData);
+        return internalClass->vtable->construct(this, callData);
     }
     inline ReturnedValue call(CallData *callData) {
-        return vtbl->call(this, callData);
+        return internalClass->vtable->call(this, callData);
     }
 
     static FunctionObject *cast(const Value &v) {
@@ -194,7 +194,7 @@ struct IndexedBuiltinFunction: FunctionObject
         , code(code)
         , index(index)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
 
     static ReturnedValue construct(Managed *m, CallData *)
index 7d7338f..1d465df 100644 (file)
@@ -119,6 +119,8 @@ struct Object;
 struct ObjectPrototype;
 struct ObjectIterator;
 struct ExecutionContext;
+struct GlobalContext;
+struct CallContext;
 struct ScriptFunction;
 struct InternalClass;
 struct Property;
index 33a9755..d4c4dbf 100644 (file)
@@ -349,7 +349,7 @@ DEFINE_MANAGED_VTABLE(EvalFunction);
 EvalFunction::EvalFunction(ExecutionContext *scope)
     : FunctionObject(scope, scope->engine->id_eval)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1));
 }
 
index cb799a4..3b4890f 100644 (file)
@@ -126,10 +126,21 @@ uint PropertyHash::lookup(const Identifier *identifier) const
     }
 }
 
+InternalClass::InternalClass(ExecutionEngine *engine)
+    : engine(engine)
+    , prototype(0)
+    , vtable(&Managed::static_vtbl)
+    , m_sealed(0)
+    , m_frozen(0)
+    , size(0)
+{
+}
+
 
 InternalClass::InternalClass(const QV4::InternalClass &other)
     : engine(other.engine)
     , prototype(other.prototype)
+    , vtable(other.vtable)
     , propertyTable(other.propertyTable)
     , nameMap(other.nameMap)
     , propertyData(other.propertyData)
@@ -184,11 +195,41 @@ InternalClass *InternalClass::changePrototype(Object *proto)
 
     // create a new class and add it to the tree
     InternalClass *newClass;
-    if (this == engine->emptyClass) {
+    if (!size) {
         newClass = engine->newClass(*this);
         newClass->prototype = proto;
     } else {
-        newClass = engine->emptyClass->changePrototype(proto);
+        newClass = engine->emptyClass->changeVTable(vtable);
+        newClass = newClass->changePrototype(proto);
+        for (uint i = 0; i < size; ++i)
+            newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
+    }
+
+    transitions.insert(t, newClass);
+    return newClass;
+}
+
+InternalClass *InternalClass::changeVTable(const ManagedVTable *vt)
+{
+    if (vtable == vt)
+        return this;
+
+    Transition t;
+    t.vtable = vt;
+    t.flags = Transition::VTableChange;
+
+    QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
+    if (tit != transitions.constEnd())
+        return tit.value();
+
+    // create a new class and add it to the tree
+    InternalClass *newClass;
+    if (this == engine->emptyClass) {
+        newClass = engine->newClass(*this);
+        newClass->vtable = vt;
+    } else {
+        newClass = engine->emptyClass->changeVTable(vt);
+        newClass = newClass->changePrototype(prototype);
         for (uint i = 0; i < size; ++i)
             newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
     }
@@ -343,7 +384,9 @@ void InternalClass::markObjects()
 
     for (QHash<Transition, InternalClass *>::ConstIterator it = transitions.begin(), end = transitions.end();
          it != end; ++it) {
-        if (it.key().flags == Transition::ProtoChange) {
+        if (it.key().flags == Transition::VTableChange) {
+            it.value()->markObjects();
+        } else if (it.key().flags == Transition::ProtoChange) {
             Q_ASSERT(it.value()->prototype);
             it.value()->prototype->mark(engine);
         }
index 9586637..621a6ab 100644 (file)
@@ -53,6 +53,7 @@ struct String;
 struct ExecutionEngine;
 struct Object;
 struct Identifier;
+struct ManagedVTable;
 
 struct PropertyHashData;
 struct PropertyHash
@@ -198,9 +199,14 @@ struct InternalClassTransition
     union {
         Identifier *id;
         Object *prototype;
+        const ManagedVTable *vtable;
     };
     int flags;
-    enum { ProtoChange = 0x100 };
+    enum {
+        // range 0-0xff is reserved for attribute changes
+        ProtoChange = 0x100,
+        VTableChange = 0x200
+    };
 
     bool operator==(const InternalClassTransition &other) const
     { return id == other.id && flags == other.flags; }
@@ -210,6 +216,8 @@ uint qHash(const QV4::InternalClassTransition &t, uint = 0);
 struct InternalClass {
     ExecutionEngine *engine;
     Object *prototype;
+    const ManagedVTable *vtable;
+
     PropertyHash propertyTable; // id to valueIndex
     SharedInternalClassData<String *> nameMap;
     SharedInternalClassData<PropertyAttributes> propertyData;
@@ -223,6 +231,7 @@ struct InternalClass {
     uint size;
 
     InternalClass *changePrototype(Object *proto);
+    InternalClass *changeVTable(const ManagedVTable *vt);
     InternalClass *addMember(StringRef string, PropertyAttributes data, uint *index = 0);
     InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0);
     InternalClass *changeMember(String *string, PropertyAttributes data, uint *index = 0);
@@ -238,7 +247,7 @@ struct InternalClass {
 
 private:
     friend struct ExecutionEngine;
-    InternalClass(ExecutionEngine *engine) : engine(engine), prototype(0), m_sealed(0), m_frozen(0), size(0) {}
+    InternalClass(ExecutionEngine *engine);
     InternalClass(const InternalClass &other);
 };
 
index 895ae8d..9b52abb 100644 (file)
@@ -81,7 +81,6 @@ void Managed::operator delete(void *ptr)
         return;
 
     Managed *m = static_cast<Managed *>(ptr);
-    m->vtbl = 0;
     m->_data = 0;
     m->markBit = 0;
     m->~Managed();
@@ -177,6 +176,12 @@ QString Managed::className() const
     return QString::fromLatin1(s);
 }
 
+void Managed::setVTable(const ManagedVTable *vt)
+{
+    Q_ASSERT(internalClass);
+    internalClass = internalClass->changeVTable(vt);
+}
+
 ReturnedValue Managed::construct(Managed *m, CallData *)
 {
     return m->engine()->current->throwTypeError();
@@ -204,40 +209,40 @@ bool Managed::isEqualTo(Managed *, Managed *)
 
 ReturnedValue Managed::get(const StringRef name, bool *hasProperty)
 {
-    return vtbl->get(this, name, hasProperty);
+    return internalClass->vtable->get(this, name, hasProperty);
 }
 
 ReturnedValue Managed::getIndexed(uint index, bool *hasProperty)
 {
-    return vtbl->getIndexed(this, index, hasProperty);
+    return internalClass->vtable->getIndexed(this, index, hasProperty);
 }
 
 void Managed::put(const StringRef name, const ValueRef value)
 {
-    vtbl->put(this, name, value);
+    internalClass->vtable->put(this, name, value);
 }
 
 void Managed::setLookup(Lookup *l, const ValueRef v)
 {
-    vtbl->setLookup(this, l, v);
+    internalClass->vtable->setLookup(this, l, v);
 }
 
 void Managed::putIndexed(uint index, const ValueRef value)
 {
-    vtbl->putIndexed(this, index, value);
+    internalClass->vtable->putIndexed(this, index, value);
 }
 
 PropertyAttributes Managed::query(StringRef name) const
 {
-    return vtbl->query(this, name);
+    return internalClass->vtable->query(this, name);
 }
 
 bool Managed::deleteProperty(const StringRef name)
 {
-    return vtbl->deleteProperty(this, name);
+    return internalClass->vtable->deleteProperty(this, name);
 }
 
 Property *Managed::advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
 {
-    return vtbl->advanceIterator(this, it, name, index, attributes);
+    return internalClass->vtable->advanceIterator(this, it, name, index, attributes);
 }
index 220363e..79316ba 100644 (file)
@@ -46,6 +46,7 @@
 #include <QtCore/QDebug>
 #include "qv4global_p.h"
 #include "qv4value_def_p.h"
+#include "qv4internalclass_p.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -155,11 +156,12 @@ private:
 
 protected:
     Managed(InternalClass *internal)
-        : _data(0), vtbl(&static_vtbl), internalClass(internal)
+        : _data(0), internalClass(internal)
     { inUse = 1; extensible = 1; }
 
 public:
     void *operator new(size_t size, MemoryManager *mm);
+    void *operator new(size_t, Managed *m) { return m; }
     void operator delete(void *ptr);
     void operator delete(void *ptr, MemoryManager *mm);
 
@@ -191,12 +193,12 @@ public:
     template <typename T>
     T *as() {
         // ### FIXME:
-        if (!this)
+        if (!this || !internalClass)
             return 0;
 #if !defined(QT_NO_QOBJECT_CHECK)
         reinterpret_cast<T *>(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast<T *>(this));
 #endif
-        return vtbl == &T::static_vtbl ? static_cast<T *>(this) : 0;
+        return internalClass->vtable == &T::static_vtbl ? static_cast<T *>(this) : 0;
     }
     template <typename T>
     const T *as() const {
@@ -206,7 +208,7 @@ public:
 #if !defined(QT_NO_QOBJECT_CHECK)
         reinterpret_cast<T *>(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast<T *>(const_cast<Managed *>(this)));
 #endif
-        return vtbl == &T::static_vtbl ? static_cast<const T *>(this) : 0;
+        return internalClass->vtable == &T::static_vtbl ? static_cast<const T *>(this) : 0;
     }
 
     String *asString() { return type == Type_String ? reinterpret_cast<String *>(this) : 0; }
@@ -237,6 +239,8 @@ public:
         *reinterpret_cast<Managed **>(this) = m;
     }
 
+    void setVTable(const ManagedVTable *vt);
+
     ReturnedValue construct(CallData *d);
     ReturnedValue call(CallData *d);
     ReturnedValue get(const StringRef name, bool *hasProperty = 0);
@@ -245,17 +249,17 @@ public:
     void putIndexed(uint index, const ValueRef value);
     PropertyAttributes query(StringRef name) const;
     PropertyAttributes queryIndexed(uint index) const
-    { return vtbl->queryIndexed(this, index); }
+    { return internalClass->vtable->queryIndexed(this, index); }
 
     bool deleteProperty(const StringRef name);
     bool deleteIndexedProperty(uint index)
-    { return vtbl->deleteIndexedProperty(this, index); }
+    { return internalClass->vtable->deleteIndexedProperty(this, index); }
     ReturnedValue getLookup(Lookup *l)
-    { return vtbl->getLookup(this, l); }
+    { return internalClass->vtable->getLookup(this, l); }
     void setLookup(Lookup *l, const ValueRef v);
 
     bool isEqualTo(Managed *other)
-    { return vtbl->isEqualTo(this, other); }
+    { return internalClass->vtable->isEqualTo(this, other); }
     Property *advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
 
     static void destroy(Managed *that) { that->_data = 0; }
@@ -292,8 +296,6 @@ public:
         };
     };
 
-protected:
-    const ManagedVTable *vtbl;
 public:
     InternalClass *internalClass;
 
@@ -332,10 +334,10 @@ inline FunctionObject *managed_cast(Managed *m)
 
 
 inline ReturnedValue Managed::construct(CallData *d) {
-    return vtbl->construct(this, d);
+    return internalClass->vtable->construct(this, d);
 }
 inline ReturnedValue Managed::call(CallData *d) {
-    return vtbl->call(this, d);
+    return internalClass->vtable->call(this, d);
 }
 
 }
index 0b15588..f67efaf 100644 (file)
@@ -424,8 +424,8 @@ void MemoryManager::mark()
     // now that we marked all roots, start marking recursively and popping from the mark stack
     while (m_d->engine->jsStackTop > markBase) {
         Managed *m = m_d->engine->popForGC();
-        Q_ASSERT (m->vtbl->markObjects);
-        m->vtbl->markObjects(m, m_d->engine);
+        Q_ASSERT (m->internalClass->vtable->markObjects);
+        m->internalClass->vtable->markObjects(m, m_d->engine);
     }
 }
 
@@ -516,9 +516,9 @@ void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size,
 #ifdef V4_USE_VALGRIND
                 VALGRIND_ENABLE_ERROR_REPORTING;
 #endif
-                if (m->vtbl->collectDeletables)
-                    m->vtbl->collectDeletables(m, deletable);
-                m->vtbl->destroy(m);
+                if (m->internalClass->vtable->collectDeletables)
+                    m->internalClass->vtable->collectDeletables(m, deletable);
+                m->internalClass->vtable->destroy(m);
 
                 m->setNextFree(*f);
 #ifdef V4_USE_VALGRIND
index 039b790..a363a06 100644 (file)
@@ -54,7 +54,7 @@ DEFINE_MANAGED_VTABLE(NumberObject);
 NumberCtor::NumberCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Number"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
index 743d35f..d122eff 100644 (file)
@@ -74,18 +74,20 @@ Object::Object(ExecutionEngine *engine)
     , memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
     , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
+
     type = Type_Object;
     flags = SimpleArray;
     memset(memberData, 0, sizeof(Property)*memberDataAlloc);
 }
 
-Object::Object(InternalClass *internalClass)
-    : Managed(internalClass)
+Object::Object(InternalClass *ic)
+    : Managed(ic)
     , memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
     , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
+
     type = Type_Object;
     flags = SimpleArray;
 
index daef18d..a155a7b 100644 (file)
@@ -280,13 +280,13 @@ public:
     void ensureMemberIndex(uint idx);
 
     inline ReturnedValue get(const StringRef name, bool *hasProperty = 0)
-    { return vtbl->get(this, name, hasProperty); }
+    { return internalClass->vtable->get(this, name, hasProperty); }
     inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
-    { return vtbl->getIndexed(this, idx, hasProperty); }
+    { return internalClass->vtable->getIndexed(this, idx, hasProperty); }
     inline void put(const StringRef name, const ValueRef v)
-    { vtbl->put(this, name, v); }
+    { internalClass->vtable->put(this, name, v); }
     inline void putIndexed(uint idx, const ValueRef v)
-    { vtbl->putIndexed(this, idx, v); }
+    { internalClass->vtable->putIndexed(this, idx, v); }
     using Managed::get;
     using Managed::getIndexed;
     using Managed::put;
@@ -331,14 +331,14 @@ struct BooleanObject: Object {
     SafeValue value;
     BooleanObject(ExecutionEngine *engine, const ValueRef val)
         : Object(engine->booleanClass) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_BooleanObject;
         value = val;
     }
 protected:
     BooleanObject(InternalClass *ic)
         : Object(ic) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_BooleanObject;
         value = Encode(false);
     }
@@ -349,14 +349,14 @@ struct NumberObject: Object {
     SafeValue value;
     NumberObject(ExecutionEngine *engine, const ValueRef val)
         : Object(engine->numberClass) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_NumberObject;
         value = val;
     }
 protected:
     NumberObject(InternalClass *ic)
         : Object(ic) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_NumberObject;
         value = Encode((int)0);
     }
index 19aedf3..6c333b3 100644 (file)
@@ -89,7 +89,7 @@ struct ForEachIteratorObject: Object {
     ObjectIterator it;
     ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o)
         : Object(ctx->engine), it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_ForeachIteratorObject;
     }
 
index f17bd7d..a39b3d9 100644 (file)
@@ -77,7 +77,7 @@ DEFINE_MANAGED_VTABLE(ObjectCtor);
 ObjectCtor::ObjectCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("Object"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
index 85e6878..6696be9 100644 (file)
@@ -241,7 +241,7 @@ QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
     : Object(engine)
     , m_object(object)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 
     Scope scope(engine);
     ScopedObject protectThis(scope, this);
@@ -1726,7 +1726,7 @@ QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index
     , m_object(object)
     , m_index(index)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     subtype = WrappedQtMethod;
     m_qmlGlobal = qmlGlobal;
 }
@@ -1847,7 +1847,7 @@ QmlSignalHandler::QmlSignalHandler(ExecutionEngine *engine, QObject *object, int
     , m_object(object)
     , m_signalIndex(signalIndex)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 DEFINE_MANAGED_VTABLE(QmlSignalHandler);
index 5ec6306..1a6d4c8 100644 (file)
@@ -99,7 +99,7 @@ RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase,
     , m_ignoreCase(ignoreCase)
     , m_multiLine(multiline)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     type = Type_RegExpObject;
 
     if (!engine)
index a859722..3b69c92 100644 (file)
@@ -142,7 +142,7 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re)
 
 void RegExpObject::init(ExecutionEngine *engine)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     type = Type_RegExpObject;
 
     Scope scope(engine);
@@ -237,7 +237,7 @@ DEFINE_MANAGED_VTABLE(RegExpCtor);
 RegExpCtor::RegExpCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("RegExp"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
index 17a19b5..d56e705 100644 (file)
@@ -41,7 +41,7 @@
 #ifndef QV4SCOPEDVALUE_P_H
 #define QV4SCOPEDVALUE_P_H
 
-#include "qv4engine_p.h"
+#include "qv4context_p.h"
 #include "qv4value_def_p.h"
 
 QT_BEGIN_NAMESPACE
index c65f1ba..c1f86f9 100644 (file)
@@ -67,7 +67,7 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec
 {
     Q_ASSERT(scope->inUse);
 
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     function = f;
     function->compilationUnit->ref();
     needsActivation = function->needsActivation();
@@ -88,7 +88,7 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml)
 {
     Q_ASSERT(scope->inUse);
 
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     function = 0;
     needsActivation = false;
 
@@ -140,7 +140,7 @@ struct CompilationUnitHolder : public QV4::Object
         , unit(unit)
     {
         unit->ref();
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
     ~CompilationUnitHolder()
     {
index 26e4dcb..3b3bff4 100644 (file)
@@ -174,7 +174,7 @@ public:
         , m_isReference(false)
     {
         type = Type_QmlSequence;
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         flags &= ~SimpleArray;
         QV4::Scope scope(engine);
         QV4::ScopedObject protectThis(scope, this);
@@ -189,7 +189,7 @@ public:
         , m_isReference(true)
     {
         type = Type_QmlSequence;
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         flags &= ~SimpleArray;
         QV4::Scope scope(engine);
         QV4::ScopedObject protectThis(scope, this);
index 37508e7..18ffde2 100644 (file)
@@ -257,7 +257,8 @@ String::String(ExecutionEngine *engine, const QString &text)
 {
     _text->ref.ref();
     len = _text->size;
-    vtbl = &static_vtbl;
+    if (engine)
+        setVTable(&static_vtbl);
     type = Type_String;
     subtype = StringType_Unknown;
 }
@@ -268,7 +269,7 @@ String::String(ExecutionEngine *engine, String *l, String *r)
     , stringHash(UINT_MAX), largestSubLength(qMax(l->largestSubLength, r->largestSubLength))
     , len(l->len + r->len)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     type = Type_String;
     subtype = StringType_Unknown;
 
index 545e08d..a420dc1 100644 (file)
@@ -63,7 +63,7 @@ struct Q_QML_EXPORT String : public Managed {
     String()
         : Managed(0), _text(QStringData::sharedNull()), identifier(0)
         , stringHash(UINT_MAX), largestSubLength(0), len(0)
-    { vtbl = &static_vtbl; type = Type_String; subtype = StringType_Unknown; }
+    { setVTable(&static_vtbl); type = Type_String; subtype = StringType_Unknown; }
     String(ExecutionEngine *engine, const QString &text);
     String(ExecutionEngine *engine, String *l, String *n);
     ~String() {
index bff8f1f..6ad0a7c 100644 (file)
@@ -80,7 +80,7 @@ DEFINE_MANAGED_VTABLE(StringObject);
 StringObject::StringObject(InternalClass *ic)
     : Object(ic)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     type = Type_StringObject;
 
     Scope scope(engine());
@@ -96,7 +96,7 @@ StringObject::StringObject(InternalClass *ic)
 StringObject::StringObject(ExecutionEngine *engine, const ValueRef val)
     : Object(engine->stringClass)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     type = Type_StringObject;
 
     Scope scope(engine);
@@ -172,7 +172,7 @@ DEFINE_MANAGED_VTABLE(StringCtor);
 StringCtor::StringCtor(ExecutionContext *scope)
     : FunctionObject(scope, QStringLiteral("String"))
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
index 470e8e2..e3aa0c9 100644 (file)
@@ -56,7 +56,7 @@ VariantObject::VariantObject(InternalClass *ic)
     , ExecutionEngine::ScarceResourceData(QVariant())
     , m_vmePropertyReferenceCount(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
@@ -64,7 +64,7 @@ VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
     , ExecutionEngine::ScarceResourceData(value)
     , m_vmePropertyReferenceCount(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     if (isScarce())
         engine->scarceResources.insert(this);
 }
index ae246f5..ffdc808 100644 (file)
@@ -1491,7 +1491,7 @@ QmlIncubatorObject::QmlIncubatorObject(QV8Engine *engine, QQmlIncubator::Incubat
 {
     incubator.reset(new QQmlComponentIncubator(this, m));
     v8 = engine;
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 
     valuemap = QV4::Primitive::undefinedValue();
     qmlGlobal = QV4::Primitive::undefinedValue();
index 54b540b..2814b2b 100644 (file)
@@ -66,7 +66,7 @@ QmlContextWrapper::QmlContextWrapper(QV8Engine *engine, QQmlContextData *context
       v8(engine), readOnly(true), ownsContext(ownsContext), isNullWrapper(false),
       context(context), scopeObject(scopeObject), idObjectsWrapper(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 QmlContextWrapper::~QmlContextWrapper()
@@ -439,7 +439,7 @@ QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrappe
     : Object(engine)
     , contextWrapper(contextWrapper)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
index 73dc319..2b3fcd8 100644 (file)
@@ -56,7 +56,7 @@ QmlListWrapper::QmlListWrapper(QV8Engine *engine)
     : Object(QV8Engine::getV4(engine)),
       v8(engine)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
     flags &= ~SimpleArray;
 }
 
index 5e8130f..c8a9219 100644 (file)
@@ -61,7 +61,7 @@ public:
     QQmlLocaleData(QV4::ExecutionEngine *engine)
         : QV4::Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         type = Type_Object;
     }
 
index 258442b..db594e1 100644 (file)
@@ -60,7 +60,7 @@ QmlTypeWrapper::QmlTypeWrapper(QV8Engine *engine)
     : Object(QV8Engine::getV4(engine)),
       v8(engine), mode(IncludeEnums), type(0), typeNamespace(0), importNamespace(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 QmlTypeWrapper::~QmlTypeWrapper()
index d733694..341daf2 100644 (file)
@@ -79,7 +79,7 @@ QmlValueTypeWrapper::QmlValueTypeWrapper(QV8Engine *engine, ObjectType objectTyp
     : Object(QV8Engine::getV4(engine)), objectType(objectType)
 {
     v8 = engine;
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 }
 
 QmlValueTypeWrapper::~QmlValueTypeWrapper()
index 18e3e33..e31b1c4 100644 (file)
@@ -192,7 +192,7 @@ public:
         , list(list)
         , d(data)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
 
         if (d)
             d->addref();
@@ -226,7 +226,7 @@ public:
         : Object(engine)
         , d(data)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
 
         if (d)
             d->addref();
@@ -258,7 +258,7 @@ public:
     NodePrototype(ExecutionEngine *engine)
         : Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
 
         Scope scope(engine);
         ScopedObject protectThis(scope, this);
@@ -312,7 +312,7 @@ class Node : public Object
         : Object(engine)
         , d(data)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
 
         if (d)
             d->addref();
@@ -1605,7 +1605,7 @@ struct QQmlXMLHttpRequestWrapper : public Object
         : Object(engine)
         , request(request)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
     ~QQmlXMLHttpRequestWrapper() {
         delete request;
@@ -1626,7 +1626,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
     QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
         : FunctionObject(engine->rootContext, QStringLiteral("XMLHttpRequest"))
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         Scope scope(engine);
         ScopedValue protectThis(scope, this);
 
index bbb07cf..c79ffb7 100644 (file)
@@ -90,7 +90,7 @@ QV4::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
     , m_platform(0)
     , m_application(0)
 {
-    vtbl = &static_vtbl;
+    setVTable(&static_vtbl);
 
     Scope scope(v4);
     ScopedObject protectThis(scope, this);
@@ -1183,7 +1183,7 @@ struct BindingFunction : public QV4::FunctionObject
         : QV4::FunctionObject(originalFunction->scope, originalFunction->name)
         , originalFunction(originalFunction)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         bindingKeyFlag = true;
     }
 
index 754d008..19e2a40 100644 (file)
@@ -71,7 +71,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
         , code(code)
         , flag(flag)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
 
     static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
@@ -3144,7 +3144,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object
     QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
         : Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
 
     static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
@@ -3183,7 +3183,7 @@ public:
     QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine)
         : Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         flags &= ~SimpleArray;
     }
     virtual ~QQmlDelegateModelGroupChangeArray() {}
index 066c8e7..f78cf38 100644 (file)
@@ -165,7 +165,7 @@ struct QQmlDelegateModelItemObject : QV4::Object
     QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
         : Object(engine)
         , item(item)
-    { vtbl = &static_vtbl; }
+    { setVTable(&static_vtbl); }
     ~QQmlDelegateModelItemObject();
 
     static void destroy(Managed *that);
index 373efa3..2bc9df3 100644 (file)
@@ -484,7 +484,7 @@ public:
     QQuickJSContext2D(QV4::ExecutionEngine *engine)
         : QV4::Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
     QQuickContext2D* context;
 
@@ -653,7 +653,7 @@ public:
       , patternRepeatX(false)
       , patternRepeatY(false)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
     QBrush brush;
     bool patternRepeatX:1;
@@ -870,7 +870,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object
     QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine)
         : QV4::Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         flags &= ~SimpleArray;
     }
 
@@ -893,7 +893,7 @@ struct QQuickJSContext2DImageData : public QV4::Object
     QQuickJSContext2DImageData(QV4::ExecutionEngine *engine)
         : QV4::Object(engine)
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
         pixelData = QV4::Primitive::undefinedValue();
 
         QV4::Scope scope(engine);
index 32a45d9..9c10851 100644 (file)
@@ -72,7 +72,7 @@ using namespace QV4;
 struct Print: FunctionObject
 {
     Print(ExecutionContext *scope): FunctionObject(scope, QStringLiteral("print")) {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
 
     static ReturnedValue call(Managed *, CallData *callData)
@@ -97,7 +97,7 @@ struct GC: public FunctionObject
     GC(ExecutionContext* scope)
         : FunctionObject(scope, QStringLiteral("gc"))
     {
-        vtbl = &static_vtbl;
+        setVTable(&static_vtbl);
     }
     static ReturnedValue call(Managed *m, CallData *)
     {