From 0f32303e5cc9c539aa8698cab2b8cc2e946d885a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 21 Nov 2013 14:26:08 +0100 Subject: [PATCH] Remove setVTable calls in performance critical areas 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 --- src/qml/jsruntime/qv4argumentsobject.cpp | 2 +- src/qml/jsruntime/qv4context_p.h | 3 +- src/qml/jsruntime/qv4dateobject_p.h | 1 - src/qml/jsruntime/qv4engine.cpp | 55 ++++++++++++++++++-------------- src/qml/jsruntime/qv4engine_p.h | 8 +++-- src/qml/jsruntime/qv4functionobject.cpp | 44 +++++++++++++++---------- src/qml/jsruntime/qv4functionobject_p.h | 3 ++ src/qml/jsruntime/qv4internalclass.cpp | 6 ++++ src/qml/jsruntime/qv4internalclass_p.h | 1 + src/qml/jsruntime/qv4lookup.cpp | 2 +- src/qml/jsruntime/qv4managed_p.h | 5 ++- src/qml/jsruntime/qv4object.cpp | 5 +-- src/qml/jsruntime/qv4object_p.h | 2 -- src/qml/jsruntime/qv4regexp.cpp | 3 +- src/qml/jsruntime/qv4sequenceobject.cpp | 7 ++-- src/qml/jsruntime/qv4string.cpp | 15 ++++----- src/qml/jsruntime/qv4string_p.h | 2 +- src/qml/jsruntime/qv4stringobject.cpp | 2 +- src/qml/jsruntime/qv4variantobject.cpp | 2 -- src/qml/qml/qqmllocale.cpp | 2 +- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 2 +- 21 files changed, 97 insertions(+), 75 deletions(-) diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 0fd0242..3ec11cc 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -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) diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 2cdcf2b..f2650b2 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -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; diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index f74037a..9c451dd 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -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; } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index b50d4d8..b3d3214 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #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.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); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 77378fb..67a7077 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -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; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 6ca1187..b9318e7 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -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 f(scope, that, Scoped::Cast); - InternalClass *ic = v4->objectClass; - Scoped proto(scope, f->get(v4->id_prototype)); - if (!!proto) - ic = v4->emptyClass->changePrototype(proto.getPointer()); + InternalClass *ic = f->internalClassForConstructor(); Scoped 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 f(scope, static_cast(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 f(scope, static_cast(that)); - InternalClass *ic = v4->objectClass; - Scoped 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; diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 2e1f1d1..e0ee720 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -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); diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 3b4890f..729ed12 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -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) diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 621a6ab..b25b895 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -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); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index f67b24c..29926e9 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -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; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 79316ba..388c71d 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -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); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index d122eff..e2b3b6e 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -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; diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index a155a7b..23f2f68 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -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; } diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 1a6d4c8..41ff9f9 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -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) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 3b3bff4..1389632 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -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); diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 18ffde2..e5633eb 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -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(text).data_ptr()) + : Managed(engine->stringClass), _text(const_cast(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; diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index a420dc1..64e15b0 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -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() { diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 6ad0a7c..57c59fe 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -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; diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index e3aa0c9..dfa4ac5 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -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); } diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index c8a9219..36e0da5 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -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) diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index c79ffb7..41d5de0 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -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); } -- 2.7.4