Remove setVTable calls in performance critical areas
authorLars Knoll <lars.knoll@digia.com>
Thu, 21 Nov 2013 13:26:08 +0000 (14:26 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 4 Dec 2013 08:45:48 +0000 (09:45 +0100)
Remove all the calls to setVTable that were in performance
critical parts of the code. This now brings performance
back to the level we had with the vtable inlined in the
Managed objects.

Change-Id: I76317cc5c53b5b700d1d3883b954407142a4c424
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
21 files changed:
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4dateobject_p.h
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4internalclass.cpp
src/qml/jsruntime/qv4internalclass_p.h
src/qml/jsruntime/qv4lookup.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4regexp.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/qqmllocale.cpp
src/qml/qml/v8/qqmlbuiltinfunctions.cpp

index 0fd0242..3ec11cc 100644 (file)
@@ -79,7 +79,7 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
     Property *lp = memberData + ArrayObject::LengthPropertyIndex;
     lp->value = Primitive::fromInt32(context->realArgumentCount);
 
-    setVTable(&static_vtbl);
+    Q_ASSERT(internalClass->vtable == &static_vtbl);
 }
 
 void ArgumentsObject::destroy(Managed *that)
index 2cdcf2b..f2650b2 100644 (file)
@@ -81,9 +81,8 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
     };
 
     ExecutionContext(ExecutionEngine *engine, ContextType t, ExecutionContext *parent)
-        : Managed(engine->emptyClass)
+        : Managed(engine->executionContextClass)
     {
-        setVTable(&static_vtbl);
         this->type = t;
         strictMode = false;
         this->engine = engine;
index f74037a..9c451dd 100644 (file)
@@ -55,7 +55,6 @@ struct DateObject: Object {
     Q_MANAGED
     SafeValue value;
     DateObject(ExecutionEngine *engine, const ValueRef date): Object(engine->dateClass) {
-        setVTable(&static_vtbl);
         type = Type_DateObject;
         value = date;
     }
index b50d4d8..b3d3214 100644 (file)
@@ -53,6 +53,7 @@
 #include <qv4mathobject_p.h>
 #include <qv4numberobject_p.h>
 #include <qv4regexpobject_p.h>
+#include <qv4regexp_p.h>
 #include <qv4variantobject_p.h>
 #include <qv4runtime_p.h>
 #include "qv4mm_p.h"
@@ -183,6 +184,9 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     identifierTable = new IdentifierTable(this);
 
     emptyClass =  new (classPool.allocate(sizeof(InternalClass))) InternalClass(this);
+    executionContextClass = emptyClass->changeVTable(&ExecutionContext::static_vtbl);
+    stringClass = emptyClass->changeVTable(&String::static_vtbl);
+    regExpValueClass = emptyClass->changeVTable(&RegExp::static_vtbl);
 
     id_undefined = newIdentifier(QStringLiteral("undefined"));
     id_null = newIdentifier(QStringLiteral("null"));
@@ -215,16 +219,16 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     id_toString = newIdentifier(QStringLiteral("toString"));
     id_valueOf = newIdentifier(QStringLiteral("valueOf"));
 
-    ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(emptyClass);
-    objectClass = emptyClass->changeVTable(&Object::static_vtbl);
-    objectClass = objectClass->changePrototype(objectPrototype);
+    ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(emptyClass->changeVTable(&ObjectPrototype::static_vtbl));
+    objectClass = InternalClass::create(this, &Object::static_vtbl, objectPrototype);
     Q_ASSERT(objectClass->vtable == &Object::static_vtbl);
 
-    arrayClass = objectClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
+    arrayClass = InternalClass::create(this, &ArrayObject::static_vtbl, objectPrototype);
+    arrayClass = arrayClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
     ArrayPrototype *arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass);
     arrayClass = arrayClass->changePrototype(arrayPrototype);
 
-    InternalClass *argsClass = objectClass->changeVTable(&ArgumentsObject::static_vtbl);
+    InternalClass *argsClass = InternalClass::create(this, &ArgumentsObject::static_vtbl, objectPrototype);
     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);
@@ -235,19 +239,19 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     initRootContext();
 
     StringPrototype *stringPrototype = new (memoryManager) StringPrototype(objectClass);
-    stringClass = emptyClass->changePrototype(stringPrototype);
+    stringObjectClass = InternalClass::create(this, &String::static_vtbl, stringPrototype);
 
     NumberPrototype *numberPrototype = new (memoryManager) NumberPrototype(objectClass);
-    numberClass = emptyClass->changePrototype(numberPrototype);
+    numberClass = InternalClass::create(this, &NumberObject::static_vtbl, numberPrototype);
 
     BooleanPrototype *booleanPrototype = new (memoryManager) BooleanPrototype(objectClass);
-    booleanClass = emptyClass->changePrototype(booleanPrototype);
+    booleanClass = InternalClass::create(this, &BooleanObject::static_vtbl, booleanPrototype);
 
     DatePrototype *datePrototype = new (memoryManager) DatePrototype(objectClass);
-    dateClass = emptyClass->changePrototype(datePrototype);
+    dateClass = InternalClass::create(this, &DateObject::static_vtbl, datePrototype);
 
-    FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(objectClass);
-    functionClass = emptyClass->changePrototype(functionPrototype);
+    FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(InternalClass::create(this, &FunctionPrototype::static_vtbl, objectPrototype));
+    functionClass = InternalClass::create(this, &FunctionObject::static_vtbl, functionPrototype);
     uint index;
     functionWithProtoClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
     Q_ASSERT(index == FunctionObject::Index_Prototype);
@@ -255,32 +259,33 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     Q_ASSERT(index == FunctionObject::Index_ProtoConstructor);
 
     RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(objectClass);
-    regExpClass = emptyClass->changePrototype(regExpPrototype);
+    regExpClass = InternalClass::create(this, &RegExpObject::static_vtbl, regExpPrototype);
     regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
     Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
     regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
     Q_ASSERT(index == RegExpObject::Index_ArrayInput);
 
     ErrorPrototype *errorPrototype = new (memoryManager) ErrorPrototype(objectClass);
-    errorClass = emptyClass->changePrototype(errorPrototype);
+    errorClass = InternalClass::create(this, &ErrorObject::static_vtbl, errorPrototype);
     EvalErrorPrototype *evalErrorPrototype = new (memoryManager) EvalErrorPrototype(errorClass);
-    evalErrorClass = emptyClass->changePrototype(evalErrorPrototype);
+    evalErrorClass = InternalClass::create(this, &EvalErrorObject::static_vtbl, evalErrorPrototype);
     RangeErrorPrototype *rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(errorClass);
-    rangeErrorClass = emptyClass->changePrototype(rangeErrorPrototype);
+    rangeErrorClass = InternalClass::create(this, &RangeErrorObject::static_vtbl, rangeErrorPrototype);
     ReferenceErrorPrototype *referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(errorClass);
-    referenceErrorClass = emptyClass->changePrototype(referenceErrorPrototype);
+    referenceErrorClass = InternalClass::create(this, &ReferenceErrorObject::static_vtbl, referenceErrorPrototype);
     SyntaxErrorPrototype *syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(errorClass);
-    syntaxErrorClass = emptyClass->changePrototype(syntaxErrorPrototype);
+    syntaxErrorClass = InternalClass::create(this, &SyntaxErrorObject::static_vtbl, syntaxErrorPrototype);
     TypeErrorPrototype *typeErrorPrototype = new (memoryManager) TypeErrorPrototype(errorClass);
-    typeErrorClass = emptyClass->changePrototype(typeErrorPrototype);
+    typeErrorClass = InternalClass::create(this, &TypeErrorObject::static_vtbl, typeErrorPrototype);
     URIErrorPrototype *uRIErrorPrototype = new (memoryManager) URIErrorPrototype(errorClass);
-    uriErrorClass = emptyClass->changePrototype(uRIErrorPrototype);
+    uriErrorClass = InternalClass::create(this, &URIErrorObject::static_vtbl, uRIErrorPrototype);
 
-    VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(objectClass);
-    variantClass = emptyClass->changePrototype(variantPrototype);
+    VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(InternalClass::create(this, &VariantPrototype::static_vtbl, objectPrototype));
+    variantClass = InternalClass::create(this, &VariantObject::static_vtbl, variantPrototype);
+    Q_ASSERT(variantClass->prototype == variantPrototype);
+    Q_ASSERT(variantPrototype->internalClass->prototype == objectPrototype);
 
-    SequencePrototype *sequencePrototype = new (memoryManager) SequencePrototype(arrayClass->changePrototype(arrayPrototype));
-    sequenceClass = emptyClass->changePrototype(sequencePrototype);
+    sequencePrototype = new (memoryManager) SequencePrototype(arrayClass);
 
     objectCtor = new (memoryManager) ObjectCtor(rootContext);
     stringCtor = new (memoryManager) StringCtor(rootContext);
@@ -315,7 +320,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     uRIErrorPrototype->init(this, uRIErrorCtor);
 
     variantPrototype->init();
-    sequencePrototype->init();
+    static_cast<SequencePrototype *>(sequencePrototype.managed())->init();
 
     //
     // set up the global object
@@ -323,6 +328,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     globalObject = newObject()->getPointer();
     rootContext->global = globalObject;
     rootContext->callData->thisObject = globalObject;
+    Q_ASSERT(globalObject->internalClass->vtable);
 
     globalObject->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
     globalObject->defineDefaultProperty(QStringLiteral("String"), stringCtor);
@@ -802,6 +808,7 @@ void ExecutionEngine::markObjects()
     syntaxErrorCtor.mark(this);
     typeErrorCtor.mark(this);
     uRIErrorCtor.mark(this);
+    sequencePrototype.mark(this);
 
     exceptionValue.mark(this);
 
index 77378fb..67a7077 100644 (file)
@@ -182,12 +182,16 @@ struct Q_QML_EXPORT ExecutionEngine
     SafeValue syntaxErrorCtor;
     SafeValue typeErrorCtor;
     SafeValue uRIErrorCtor;
+    SafeValue sequencePrototype;
 
     QQmlJS::MemoryPool classPool;
     InternalClass *emptyClass;
+    InternalClass *executionContextClass;
+    InternalClass *stringClass;
+
     InternalClass *objectClass;
     InternalClass *arrayClass;
-    InternalClass *stringClass;
+    InternalClass *stringObjectClass;
     InternalClass *booleanClass;
     InternalClass *numberClass;
     InternalClass *dateClass;
@@ -198,6 +202,7 @@ struct Q_QML_EXPORT ExecutionEngine
 
     InternalClass *regExpClass;
     InternalClass *regExpExecArrayClass;
+    InternalClass *regExpValueClass;
 
     InternalClass *errorClass;
     InternalClass *evalErrorClass;
@@ -210,7 +215,6 @@ struct Q_QML_EXPORT ExecutionEngine
     InternalClass *strictArgumentsObjectClass;
 
     InternalClass *variantClass;
-    InternalClass *sequenceClass;
 
     EvalFunction *evalFunction;
     FunctionObject *thrower;
index 6ca1187..b9318e7 100644 (file)
@@ -110,7 +110,6 @@ FunctionObject::FunctionObject(InternalClass *ic)
     , varCount(0)
     , function(0)
 {
-    setVTable(&static_vtbl);
     name = ic->engine->id_undefined;
 
     type = Type_FunctionObject;
@@ -126,7 +125,6 @@ FunctionObject::~FunctionObject()
 
 void FunctionObject::init(const StringRef n, bool createProto)
 {
-    setVTable(&static_vtbl);
     name = n;
 
     Scope s(internalClass->engine);
@@ -162,10 +160,7 @@ ReturnedValue FunctionObject::construct(Managed *that, CallData *)
     Scope scope(v4);
     Scoped<FunctionObject> f(scope, that, Scoped<FunctionObject>::Cast);
 
-    InternalClass *ic = v4->objectClass;
-    Scoped<Object> proto(scope, f->get(v4->id_prototype));
-    if (!!proto)
-        ic = v4->emptyClass->changePrototype(proto.getPointer());
+    InternalClass *ic = f->internalClassForConstructor();
     Scoped<Object> obj(scope, v4->newObject(ic));
     return obj.asReturnedValue();
 }
@@ -209,12 +204,35 @@ ReturnedValue FunctionObject::protoProperty()
         protoCacheIndex = internalClass->find(internalClass->engine->id_prototype);
     }
     if (protoCacheIndex < UINT_MAX) {
-        if (internalClass->propertyData.at(protoCacheIndex).isData())
-            return memberData[protoCacheIndex].value.asReturnedValue();
+        if (internalClass->propertyData.at(protoCacheIndex).isData()) {
+            ReturnedValue v = memberData[protoCacheIndex].value.asReturnedValue();
+            if (v != protoValue) {
+                classForConstructor = 0;
+                protoValue = v;
+            }
+            return v;
+        }
     }
+    classForConstructor = 0;
     return get(internalClass->engine->id_prototype);
 }
 
+InternalClass *FunctionObject::internalClassForConstructor()
+{
+    // need to call this first to ensure we don't use a wrong class
+    ReturnedValue proto = protoProperty();
+    if (classForConstructor)
+        return classForConstructor;
+
+    Scope scope(internalClass->engine);
+    ScopedObject p(scope, proto);
+    if (p)
+        classForConstructor = InternalClass::create(scope.engine, &Object::static_vtbl, p.getPointer());
+    else
+        classForConstructor = scope.engine->objectClass;
+
+    return classForConstructor;
+}
 
 DEFINE_MANAGED_VTABLE(FunctionCtor);
 
@@ -426,10 +444,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
     Scope scope(v4);
     Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
 
-    InternalClass *ic = v4->objectClass;
-    ScopedObject proto(scope, f->memberData[Index_Prototype].value);
-    if (proto)
-        ic = v4->emptyClass->changePrototype(proto.getPointer());
+    InternalClass *ic = f->internalClassForConstructor();
     ScopedObject obj(scope, v4->newObject(ic));
 
     ExecutionContext *context = v4->current;
@@ -511,10 +526,7 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
     Scope scope(v4);
     Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
 
-    InternalClass *ic = v4->objectClass;
-    Scoped<Object> proto(scope, f->memberData[Index_Prototype].value);
-    if (!!proto)
-        ic = v4->emptyClass->changePrototype(proto.getPointer());
+    InternalClass *ic = f->internalClassForConstructor();
     callData->thisObject = v4->newObject(ic);
 
     ExecutionContext *context = v4->current;
index 2e1f1d1..e0ee720 100644 (file)
@@ -113,6 +113,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
     Function *function;
     InternalClass *protoCacheClass;
     uint protoCacheIndex;
+    ReturnedValue protoValue;
+    InternalClass *classForConstructor;
 
     FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto = false);
     FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
@@ -138,6 +140,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
     static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function);
 
     ReturnedValue protoProperty();
+    InternalClass *internalClassForConstructor();
 
 protected:
     FunctionObject(InternalClass *ic);
index 3b4890f..729ed12 100644 (file)
@@ -180,6 +180,12 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
 
 }
 
+InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto)
+{
+    InternalClass *c = engine->emptyClass->changeVTable(vtable);
+    return c->changePrototype(proto);
+}
+
 InternalClass *InternalClass::changePrototype(Object *proto)
 {
     if (prototype == proto)
index 621a6ab..b25b895 100644 (file)
@@ -230,6 +230,7 @@ struct InternalClass {
 
     uint size;
 
+    static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto);
     InternalClass *changePrototype(Object *proto);
     InternalClass *changeVTable(const ManagedVTable *vt);
     InternalClass *addMember(StringRef string, PropertyAttributes data, uint *index = 0);
index f67b24c..29926e9 100644 (file)
@@ -93,7 +93,7 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
         break;
     case Value::Managed_Type:
         Q_ASSERT(object->isString());
-        proto = engine->stringClass->prototype;
+        proto = engine->stringObjectClass->prototype;
         if (l->name->equals(engine->id_length)) {
             // special case, as the property is on the object itself
             l->getter = stringLengthGetter;
index 79316ba..388c71d 100644 (file)
@@ -157,7 +157,10 @@ private:
 protected:
     Managed(InternalClass *internal)
         : _data(0), internalClass(internal)
-    { inUse = 1; extensible = 1; }
+    {
+        Q_ASSERT(internalClass->vtable);
+        inUse = 1; extensible = 1;
+    }
 
 public:
     void *operator new(size_t size, MemoryManager *mm);
index d122eff..e2b3b6e 100644 (file)
@@ -74,8 +74,6 @@ Object::Object(ExecutionEngine *engine)
     , memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
     , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
 {
-    setVTable(&static_vtbl);
-
     type = Type_Object;
     flags = SimpleArray;
     memset(memberData, 0, sizeof(Property)*memberDataAlloc);
@@ -86,8 +84,7 @@ Object::Object(InternalClass *ic)
     , memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
     , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
 {
-    setVTable(&static_vtbl);
-
+    Q_ASSERT(internalClass->vtable && internalClass->vtable != &Managed::static_vtbl);
     type = Type_Object;
     flags = SimpleArray;
 
index a155a7b..23f2f68 100644 (file)
@@ -331,7 +331,6 @@ struct BooleanObject: Object {
     SafeValue value;
     BooleanObject(ExecutionEngine *engine, const ValueRef val)
         : Object(engine->booleanClass) {
-        setVTable(&static_vtbl);
         type = Type_BooleanObject;
         value = val;
     }
@@ -349,7 +348,6 @@ struct NumberObject: Object {
     SafeValue value;
     NumberObject(ExecutionEngine *engine, const ValueRef val)
         : Object(engine->numberClass) {
-        setVTable(&static_vtbl);
         type = Type_NumberObject;
         value = val;
     }
index 1a6d4c8..41ff9f9 100644 (file)
@@ -92,14 +92,13 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign
 }
 
 RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
-    : Managed(engine->emptyClass)
+    : Managed(engine->regExpValueClass)
     , m_pattern(pattern)
     , m_cache(0)
     , m_subPatternCount(0)
     , m_ignoreCase(ignoreCase)
     , m_multiLine(multiline)
 {
-    setVTable(&static_vtbl);
     type = Type_RegExpObject;
 
     if (!engine)
index 3b3bff4..1389632 100644 (file)
@@ -47,6 +47,7 @@
 #include <private/qv4arrayobject_p.h>
 #include <private/qqmlengine_p.h>
 #include <private/qv4scopedvalue_p.h>
+#include <private/qv4internalclass_p.h>
 
 #include <algorithm>
 
@@ -167,14 +168,13 @@ class QQmlSequence : public QV4::Object
     Q_MANAGED
 public:
     QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
-        : QV4::Object(engine->sequenceClass)
+        : QV4::Object(InternalClass::create(engine, &static_vtbl, engine->sequencePrototype.asObject()))
         , m_container(container)
         , m_object(0)
         , m_propertyIndex(-1)
         , m_isReference(false)
     {
         type = Type_QmlSequence;
-        setVTable(&static_vtbl);
         flags &= ~SimpleArray;
         QV4::Scope scope(engine);
         QV4::ScopedObject protectThis(scope, this);
@@ -183,13 +183,12 @@ public:
     }
 
     QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
-        : QV4::Object(engine->sequenceClass)
+        : QV4::Object(InternalClass::create(engine, &static_vtbl, engine->sequencePrototype.asObject()))
         , m_object(object)
         , m_propertyIndex(propertyIndex)
         , m_isReference(true)
     {
         type = Type_QmlSequence;
-        setVTable(&static_vtbl);
         flags &= ~SimpleArray;
         QV4::Scope scope(engine);
         QV4::ScopedObject protectThis(scope, this);
index 18ffde2..e5633eb 100644 (file)
@@ -149,7 +149,7 @@ ReturnedValue String::get(Managed *m, const StringRef name, bool *hasProperty)
         return Primitive::fromInt32(that->_text->size).asReturnedValue();
     }
     PropertyAttributes attrs;
-    Property *pd = v4->stringClass->prototype->__getPropertyDescriptor__(name, &attrs);
+    Property *pd = v4->stringObjectClass->prototype->__getPropertyDescriptor__(name, &attrs);
     if (!pd || attrs.isGeneric()) {
         if (hasProperty)
             *hasProperty = false;
@@ -157,7 +157,7 @@ ReturnedValue String::get(Managed *m, const StringRef name, bool *hasProperty)
     }
     if (hasProperty)
         *hasProperty = true;
-    return v4->stringClass->prototype->getValue(that, pd, attrs);
+    return v4->stringObjectClass->prototype->getValue(that, pd, attrs);
 }
 
 ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
@@ -172,7 +172,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
         return Encode(engine->newString(that->toQString().mid(index, 1)));
     }
     PropertyAttributes attrs;
-    Property *pd = engine->stringClass->prototype->__getPropertyDescriptor__(index, &attrs);
+    Property *pd = engine->stringObjectClass->prototype->__getPropertyDescriptor__(index, &attrs);
     if (!pd || attrs.isGeneric()) {
         if (hasProperty)
             *hasProperty = false;
@@ -180,7 +180,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
     }
     if (hasProperty)
         *hasProperty = true;
-    return engine->stringClass->prototype->getValue(that, pd, attrs);
+    return engine->stringObjectClass->prototype->getValue(that, pd, attrs);
 }
 
 void String::put(Managed *m, const StringRef name, const ValueRef value)
@@ -251,25 +251,22 @@ bool String::isEqualTo(Managed *t, Managed *o)
 
 
 String::String(ExecutionEngine *engine, const QString &text)
-    : Managed(engine ? engine->emptyClass : 0), _text(const_cast<QString &>(text).data_ptr())
+    : Managed(engine->stringClass), _text(const_cast<QString &>(text).data_ptr())
     , identifier(0), stringHash(UINT_MAX)
     , largestSubLength(0)
 {
     _text->ref.ref();
     len = _text->size;
-    if (engine)
-        setVTable(&static_vtbl);
     type = Type_String;
     subtype = StringType_Unknown;
 }
 
 String::String(ExecutionEngine *engine, String *l, String *r)
-    : Managed(engine ? engine->emptyClass : 0)
+    : Managed(engine->stringClass)
     , left(l), right(r)
     , stringHash(UINT_MAX), largestSubLength(qMax(l->largestSubLength, r->largestSubLength))
     , len(l->len + r->len)
 {
-    setVTable(&static_vtbl);
     type = Type_String;
     subtype = StringType_Unknown;
 
index a420dc1..64e15b0 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)
-    { setVTable(&static_vtbl); type = Type_String; subtype = StringType_Unknown; }
+    { type = Type_String; subtype = StringType_Unknown; }
     String(ExecutionEngine *engine, const QString &text);
     String(ExecutionEngine *engine, String *l, String *n);
     ~String() {
index 6ad0a7c..57c59fe 100644 (file)
@@ -94,7 +94,7 @@ StringObject::StringObject(InternalClass *ic)
 }
 
 StringObject::StringObject(ExecutionEngine *engine, const ValueRef val)
-    : Object(engine->stringClass)
+    : Object(engine->stringObjectClass)
 {
     setVTable(&static_vtbl);
     type = Type_StringObject;
index e3aa0c9..dfa4ac5 100644 (file)
@@ -56,7 +56,6 @@ VariantObject::VariantObject(InternalClass *ic)
     , ExecutionEngine::ScarceResourceData(QVariant())
     , m_vmePropertyReferenceCount(0)
 {
-    setVTable(&static_vtbl);
 }
 
 VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
@@ -64,7 +63,6 @@ VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
     , ExecutionEngine::ScarceResourceData(value)
     , m_vmePropertyReferenceCount(0)
 {
-    setVTable(&static_vtbl);
     if (isScarce())
         engine->scarceResources.insert(this);
 }
index c8a9219..36e0da5 100644 (file)
@@ -872,7 +872,7 @@ QV4::ReturnedValue QQmlLocale::locale(QV8Engine *v8engine, const QString &locale
 
 void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
 {
-    engine->stringClass->prototype->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
+    engine->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
 }
 
 QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
index c79ffb7..41d5de0 100644 (file)
@@ -1608,7 +1608,7 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
     globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
 
     // string prototype extension
-    v4->stringClass->prototype->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
+    v4->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
 }