diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-11-24 15:38:41 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2014-12-11 15:52:13 +0100 |
commit | 8afc1f7fe24c625cdb84406cc7665f1dcabf88c4 (patch) | |
tree | 04c5d73167544182e509ce7e40bd18c29909d0a7 /src/qml | |
parent | 4322c8d7686c7cbbdf348146d32d705007b21d56 (diff) |
Move prototype back from the vtable into Object
This is the only way we can support a GC that moves
objects around in memory.
Change-Id: I1d168fae4aa9f575b730e469e762bc5b5549b886
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml')
35 files changed, 309 insertions, 327 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index bd78b7d051..e25d166172 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -264,8 +264,8 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object) obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp); // string prototype extension - v4->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("arg"), - QV4::GlobalExtensions::method_string_arg); + v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), + QV4::GlobalExtensions::method_string_arg); #endif } @@ -301,7 +301,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in { QV4::ExecutionEngine *v4 = d->m_v4Engine; QV4::Scope scope(v4); - QV4::ExecutionContext *ctx = v4->currentContext(); + QV4::ScopedContext ctx(scope, v4->currentContext()); if (ctx != v4->rootContext()) ctx = v4->pushGlobalContext(); QV4::ScopedValue result(scope); diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 78c8d6fccf..d283537292 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -39,7 +39,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArgumentsObject); Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context) - : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass) + : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass, + context->d()->engine->objectPrototype.asObject()) , context(context->d()) , fullyCreated(false) { diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index b8b9971635..9fc3114751 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -84,7 +84,7 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx) Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, int length) - : Heap::Object(e->arrayBufferClass) + : Heap::Object(e->arrayBufferClass, e->arrayBufferPrototype.asObject()) { data = QTypedArrayData<char>::allocate(length + 1); if (!data) { diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index 61a009187d..36d597fb6e 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -77,7 +77,7 @@ ReturnedValue DataViewCtor::call(Managed *that, CallData *callData) Heap::DataView::DataView(ExecutionEngine *e) - : Heap::Object(e->dataViewClass), + : Heap::Object(e->dataViewClass, e->dataViewPrototype.asObject()), buffer(0), byteLength(0), byteOffset(0) diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index c5d25e42ae..811d2f0acb 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -635,7 +635,7 @@ static double getLocalTZA() DEFINE_OBJECT_VTABLE(DateObject); Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date) - : Heap::Object(engine->dateClass) + : Heap::Object(engine->dateClass, engine->datePrototype.asObject()) { setVTable(QV4::DateObject::staticVTable()); value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN()); diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 4eba963fac..b164de6baa 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -46,13 +46,18 @@ namespace QV4 { namespace Heap { struct DateObject : Object { + DateObject(InternalClass *ic, QV4::Object *prototype) + : Object(ic, prototype) + { + value = Encode(qSNaN()); + } + DateObject(QV4::ExecutionEngine *engine, const ValueRef date) - : Object(engine->dateClass) + : Object(engine->dateClass, engine->datePrototype.asObject()) { value = date; } DateObject(QV4::ExecutionEngine *engine, const QDateTime &date); - inline DateObject(InternalClass *ic); Value value; }; @@ -74,13 +79,6 @@ struct DateObject: Object { QDateTime toQDateTime() const; }; -Heap::DateObject::DateObject(InternalClass *ic) - : Heap::Object(ic) -{ - Q_ASSERT(internalClass->vtable == QV4::DateObject::staticVTable()); - value = Primitive::fromDouble(qSNaN()); -} - struct DateCtor: FunctionObject { V4_OBJECT2(DateCtor, FunctionObject) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index ddee344114..160dbe4352 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -219,10 +219,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) classPool = new InternalClassPool; emptyClass = new (classPool) InternalClass(this); - executionContextClass = InternalClass::create(this, ExecutionContext::staticVTable(), 0); - constructClass = InternalClass::create(this, Object::staticVTable(), 0); - stringClass = InternalClass::create(this, String::staticVTable(), 0); - regExpValueClass = InternalClass::create(this, RegExp::staticVTable(), 0); + executionContextClass = InternalClass::create(this, ExecutionContext::staticVTable()); + stringClass = InternalClass::create(this, String::staticVTable()); + regExpValueClass = InternalClass::create(this, RegExp::staticVTable()); id_empty = newIdentifier(QString()); id_undefined = newIdentifier(QStringLiteral("undefined")); @@ -261,20 +260,19 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) id_buffer = newIdentifier(QStringLiteral("buffer")); id_lastIndex = newIdentifier(QStringLiteral("lastIndex")); - memberDataClass = InternalClass::create(this, MemberData::staticVTable(), 0); + memberDataClass = InternalClass::create(this, MemberData::staticVTable()); - ScopedObject objectPrototype(scope, memoryManager->alloc<ObjectPrototype>(InternalClass::create(this, ObjectPrototype::staticVTable(), 0))); - objectClass = InternalClass::create(this, Object::staticVTable(), objectPrototype); + objectPrototype = memoryManager->alloc<ObjectPrototype>(InternalClass::create(this, ObjectPrototype::staticVTable()), (QV4::Object *)0); + objectClass = InternalClass::create(this, Object::staticVTable()); Q_ASSERT(objectClass->vtable == Object::staticVTable()); - arrayClass = InternalClass::create(this, ArrayObject::staticVTable(), objectPrototype); + arrayClass = InternalClass::create(this, ArrayObject::staticVTable()); arrayClass = arrayClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable); - ScopedObject arrayPrototype(scope, memoryManager->alloc<ArrayPrototype>(arrayClass)); - arrayClass = arrayClass->changePrototype(arrayPrototype); + arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject()); - simpleArrayDataClass = InternalClass::create(this, SimpleArrayData::staticVTable(), 0); + simpleArrayDataClass = InternalClass::create(this, SimpleArrayData::staticVTable()); - InternalClass *argsClass = InternalClass::create(this, ArgumentsObject::staticVTable(), objectPrototype); + InternalClass *argsClass = InternalClass::create(this, ArgumentsObject::staticVTable()); 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); @@ -286,57 +284,56 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) Q_ASSERT(globalObject()->internalClass()->vtable); initRootContext(); - ScopedObject stringPrototype(scope, memoryManager->alloc<StringPrototype>(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype))); - stringObjectClass = InternalClass::create(this, String::staticVTable(), stringPrototype); + stringPrototype = memoryManager->alloc<StringPrototype>(InternalClass::create(this, StringPrototype::staticVTable()), objectPrototype.asObject()); + stringObjectClass = InternalClass::create(this, String::staticVTable()); - ScopedObject numberPrototype(scope, memoryManager->alloc<NumberPrototype>(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype))); - numberClass = InternalClass::create(this, NumberObject::staticVTable(), numberPrototype); + numberPrototype = memoryManager->alloc<NumberPrototype>(InternalClass::create(this, NumberPrototype::staticVTable()), objectPrototype.asObject()); + numberClass = InternalClass::create(this, NumberObject::staticVTable()); - ScopedObject booleanPrototype(scope, memoryManager->alloc<BooleanPrototype>(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype))); - booleanClass = InternalClass::create(this, BooleanObject::staticVTable(), booleanPrototype); + booleanPrototype = memoryManager->alloc<BooleanPrototype>(InternalClass::create(this, BooleanPrototype::staticVTable()), objectPrototype.asObject()); + booleanClass = InternalClass::create(this, BooleanObject::staticVTable()); - ScopedObject datePrototype(scope, memoryManager->alloc<DatePrototype>(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype))); - dateClass = InternalClass::create(this, DateObject::staticVTable(), datePrototype); + datePrototype = memoryManager->alloc<DatePrototype>(InternalClass::create(this, DatePrototype::staticVTable()), objectPrototype.asObject()); + dateClass = InternalClass::create(this, DateObject::staticVTable()); - InternalClass *functionProtoClass = InternalClass::create(this, FunctionObject::staticVTable(), objectPrototype); + InternalClass *functionProtoClass = InternalClass::create(this, FunctionObject::staticVTable()); uint index; functionProtoClass = functionProtoClass->addMember(id_prototype, Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); - ScopedObject functionPrototype(scope, memoryManager->alloc<FunctionPrototype>(functionProtoClass)); - functionClass = InternalClass::create(this, FunctionObject::staticVTable(), functionPrototype); + functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject()); + functionClass = InternalClass::create(this, FunctionObject::staticVTable()); functionClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor); - Scoped<RegExpPrototype> regExpPrototype(scope, memoryManager->alloc<RegExpPrototype>(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype))); - regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype.getPointer()); + regExpPrototype = memoryManager->alloc<RegExpPrototype>(this); + regExpClass = InternalClass::create(this, RegExpObject::staticVTable()); 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); - ScopedObject errorPrototype(scope, memoryManager->alloc<ErrorPrototype>(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype))); - errorClass = InternalClass::create(this, ErrorObject::staticVTable(), errorPrototype); - ScopedObject evalErrorPrototype(scope, memoryManager->alloc<EvalErrorPrototype>(errorClass)); - evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable(), evalErrorPrototype); - ScopedObject rangeErrorPrototype(scope, memoryManager->alloc<RangeErrorPrototype>(errorClass)); - rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable(), rangeErrorPrototype); - ScopedObject referenceErrorPrototype(scope, memoryManager->alloc<ReferenceErrorPrototype>(errorClass)); - referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable(), referenceErrorPrototype); - ScopedObject syntaxErrorPrototype(scope, memoryManager->alloc<SyntaxErrorPrototype>(errorClass)); - syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable(), syntaxErrorPrototype); - ScopedObject typeErrorPrototype(scope, memoryManager->alloc<TypeErrorPrototype>(errorClass)); - typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable(), typeErrorPrototype); - ScopedObject uRIErrorPrototype(scope, memoryManager->alloc<URIErrorPrototype>(errorClass)); - uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable(), uRIErrorPrototype); - - ScopedObject variantPrototype(scope, memoryManager->alloc<VariantPrototype>(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype))); - variantClass = InternalClass::create(this, VariantObject::staticVTable(), variantPrototype); - Q_ASSERT(variantClass->prototype == variantPrototype); - Q_ASSERT(variantPrototype->internalClass()->prototype == objectPrototype); - - sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass)); + errorPrototype = memoryManager->alloc<ErrorPrototype>(InternalClass::create(this, ErrorObject::staticVTable()), objectPrototype.asObject()); + errorClass = InternalClass::create(this, ErrorObject::staticVTable()); + evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(errorClass, errorPrototype.asObject()); + evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable()); + rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(errorClass, errorPrototype.asObject()); + rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable()); + referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(errorClass, errorPrototype.asObject()); + referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable()); + syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(errorClass, errorPrototype.asObject()); + syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable()); + typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(errorClass, errorPrototype.asObject()); + typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable()); + uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(errorClass, errorPrototype.asObject()); + uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable()); + + variantPrototype = memoryManager->alloc<VariantPrototype>(InternalClass::create(this, VariantPrototype::staticVTable()), objectPrototype.asObject()); + variantClass = InternalClass::create(this, VariantObject::staticVTable()); + Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()); + + sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject())); objectCtor = memoryManager->alloc<ObjectCtor>(rootContext()); stringCtor = memoryManager->alloc<StringCtor>(rootContext()); @@ -354,43 +351,43 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(rootContext()); uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(rootContext()); - static_cast<ObjectPrototype *>(objectPrototype.getPointer())->init(this, objectCtor.asObject()); - static_cast<StringPrototype *>(stringPrototype.getPointer())->init(this, stringCtor.asObject()); - static_cast<NumberPrototype *>(numberPrototype.getPointer())->init(this, numberCtor.asObject()); - static_cast<BooleanPrototype *>(booleanPrototype.getPointer())->init(this, booleanCtor.asObject()); - static_cast<ArrayPrototype *>(arrayPrototype.getPointer())->init(this, arrayCtor.asObject()); - static_cast<DatePrototype *>(datePrototype.getPointer())->init(this, dateCtor.asObject()); - static_cast<FunctionPrototype *>(functionPrototype.getPointer())->init(this, functionCtor.asObject()); - static_cast<RegExpPrototype *>(regExpPrototype.getPointer())->init(this, regExpCtor.asObject()); - static_cast<ErrorPrototype *>(errorPrototype.getPointer())->init(this, errorCtor.asObject()); - static_cast<EvalErrorPrototype *>(evalErrorPrototype.getPointer())->init(this, evalErrorCtor.asObject()); - static_cast<RangeErrorPrototype *>(rangeErrorPrototype.getPointer())->init(this, rangeErrorCtor.asObject()); - static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.getPointer())->init(this, referenceErrorCtor.asObject()); - static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.getPointer())->init(this, syntaxErrorCtor.asObject()); - static_cast<TypeErrorPrototype *>(typeErrorPrototype.getPointer())->init(this, typeErrorCtor.asObject()); - static_cast<URIErrorPrototype *>(uRIErrorPrototype.getPointer())->init(this, uRIErrorCtor.asObject()); - - static_cast<VariantPrototype *>(variantPrototype.getPointer())->init(); + static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject()); + static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject()); + static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject()); + static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject()); + static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject()); + static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject()); + static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject()); + static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject()); + static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject()); + static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject()); + static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject()); + static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject()); + static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject()); + static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject()); + static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject()); + + static_cast<VariantPrototype *>(variantPrototype.asObject())->init(); sequencePrototype.cast<SequencePrototype>()->init(); // typed arrays arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(rootContext()); - Scoped<ArrayBufferPrototype> arrayBufferPrototype(scope, memoryManager->alloc<ArrayBufferPrototype>(objectClass)); - arrayBufferPrototype->init(this, arrayBufferCtor.asObject()); - arrayBufferClass = InternalClass::create(this, ArrayBuffer::staticVTable(), arrayBufferPrototype); + arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(objectClass, objectPrototype.asObject()); + static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject()); + arrayBufferClass = InternalClass::create(this, ArrayBuffer::staticVTable()); dataViewCtor = memoryManager->alloc<DataViewCtor>(rootContext()); - Scoped<DataViewPrototype> dataViewPrototype(scope, memoryManager->alloc<DataViewPrototype>(objectClass)); - dataViewPrototype->init(this, dataViewCtor.asObject()); - dataViewClass = InternalClass::create(this, DataView::staticVTable(), dataViewPrototype); + dataViewPrototype = memoryManager->alloc<DataViewPrototype>(objectClass, objectPrototype.asObject()); + static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject()); + dataViewClass = InternalClass::create(this, DataView::staticVTable()); for (int i = 0; i < Heap::TypedArray::NTypes; ++i) { typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(rootContext(), Heap::TypedArray::Type(i)); - Scoped<TypedArrayPrototype> typedArrayPrototype(scope, memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i))); - typedArrayPrototype->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject())); - typedArrayClasses[i] = InternalClass::create(this, TypedArray::staticVTable(), typedArrayPrototype); + typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i)); + typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject())); + typedArrayClasses[i] = InternalClass::create(this, TypedArray::staticVTable()); } // @@ -422,8 +419,8 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) for (int i = 0; i < Heap::TypedArray::NTypes; ++i) globalObject()->defineDefaultProperty((str = typedArrayCtors[i].asFunctionObject()->name())->toQString(), typedArrayCtors[i]); ScopedObject o(scope); - globalObject()->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype)))); - globalObject()->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype)))); + globalObject()->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this))); + globalObject()->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this))); globalObject()->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue()); globalObject()->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN())); @@ -526,10 +523,10 @@ Heap::Object *ExecutionEngine::newObject() return object->d(); } -Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass) +Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype) { Scope scope(this); - ScopedObject object(scope, memoryManager->alloc<Object>(internalClass)); + ScopedObject object(scope, memoryManager->alloc<Object>(internalClass, prototype)); return object->d(); } @@ -585,10 +582,10 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list) return object->d(); } -Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic) +Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *prototype) { Scope scope(this); - ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic)); + ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic, prototype)); return object->d(); } @@ -639,7 +636,7 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re) Heap::Object *ExecutionEngine::newErrorObject(const ValueRef value) { Scope scope(this); - ScopedObject object(scope, memoryManager->alloc<ErrorObject>(errorClass, value)); + ScopedObject object(scope, memoryManager->alloc<ErrorObject>(errorClass, errorPrototype.asObject(), value)); return object->d(); } @@ -951,8 +948,30 @@ void ExecutionEngine::markObjects() dataViewCtor.mark(this); for (int i = 0; i < Heap::TypedArray::NTypes; ++i) typedArrayCtors[i].mark(this); + + objectPrototype.mark(this); + arrayPrototype.mark(this); + stringPrototype.mark(this); + numberPrototype.mark(this); + booleanPrototype.mark(this); + datePrototype.mark(this); + functionPrototype.mark(this); + regExpPrototype.mark(this); + errorPrototype.mark(this); + evalErrorPrototype.mark(this); + rangeErrorPrototype.mark(this); + referenceErrorPrototype.mark(this); + syntaxErrorPrototype.mark(this); + typeErrorPrototype.mark(this); + uRIErrorPrototype.mark(this); + variantPrototype.mark(this); sequencePrototype.mark(this); + arrayBufferPrototype.mark(this); + dataViewPrototype.mark(this); + for (int i = 0; i < Heap::TypedArray::NTypes; ++i) + typedArrayPrototype[i].mark(this); + exceptionValue.mark(this); thrower->mark(this); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index ad9fde3d86..dc75d37a86 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -141,16 +141,36 @@ public: Value syntaxErrorCtor; Value typeErrorCtor; Value uRIErrorCtor; - Value sequencePrototype; Value arrayBufferCtor; Value dataViewCtor; enum { NTypedArrayTypes = 9 }; // avoid header dependency Value typedArrayCtors[NTypedArrayTypes]; + Value objectPrototype; + Value arrayPrototype; + Value stringPrototype; + Value numberPrototype; + Value booleanPrototype; + Value datePrototype; + Value functionPrototype; + Value regExpPrototype; + Value errorPrototype; + Value evalErrorPrototype; + Value rangeErrorPrototype; + Value referenceErrorPrototype; + Value syntaxErrorPrototype; + Value typeErrorPrototype; + Value uRIErrorPrototype; + Value variantPrototype; + Value sequencePrototype; + + Value arrayBufferPrototype; + Value dataViewPrototype; + Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here + InternalClassPool *classPool; InternalClass *emptyClass; InternalClass *executionContextClass; - InternalClass *constructClass; InternalClass *stringClass; InternalClass *objectClass; @@ -264,7 +284,7 @@ public: ExecutionContext *popContext(); Heap::Object *newObject(); - Heap::Object *newObject(InternalClass *internalClass); + Heap::Object *newObject(InternalClass *internalClass, Object *prototype); Heap::String *newString(const QString &s); Heap::String *newIdentifier(const QString &text); @@ -275,7 +295,7 @@ public: Heap::ArrayObject *newArrayObject(int count = 0); Heap::ArrayObject *newArrayObject(const QStringList &list); - Heap::ArrayObject *newArrayObject(InternalClass *ic); + Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype); Heap::DateObject *newDateObject(const ValueRef value); Heap::DateObject *newDateObject(const QDateTime &dt); diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 7fe0574d6b..d08619f881 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -63,8 +63,8 @@ using namespace QV4; -Heap::ErrorObject::ErrorObject(InternalClass *ic) - : Heap::Object(ic) +Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype) + : Heap::Object(ic, prototype) { Scope scope(ic->engine); Scoped<QV4::ErrorObject> e(scope, this); @@ -73,8 +73,8 @@ Heap::ErrorObject::ErrorObject(InternalClass *ic) e->defineDefaultProperty(QStringLiteral("name"), s); } -Heap::ErrorObject::ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t) - : Heap::Object(ic) +Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const ValueRef message, ErrorType t) + : Heap::Object(ic, prototype) { subtype = t; @@ -95,8 +95,8 @@ Heap::ErrorObject::ErrorObject(InternalClass *ic, const ValueRef message, ErrorT } } -Heap::ErrorObject::ErrorObject(InternalClass *ic, const QString &message, ErrorObject::ErrorType t) - : Heap::Object(ic) +Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorObject::ErrorType t) + : Heap::Object(ic, prototype) { subtype = t; @@ -117,8 +117,8 @@ Heap::ErrorObject::ErrorObject(InternalClass *ic, const QString &message, ErrorO } } -Heap::ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) - : Heap::Object(ic) +Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) + : Heap::Object(ic, prototype) { subtype = t; @@ -183,57 +183,57 @@ DEFINE_OBJECT_VTABLE(ErrorObject); DEFINE_OBJECT_VTABLE(SyntaxErrorObject); Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg) - : Heap::ErrorObject(engine->syntaxErrorClass, msg, SyntaxError) + : Heap::ErrorObject(engine->syntaxErrorClass, engine->syntaxErrorPrototype.asObject(), msg, SyntaxError) { } Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError) + : Heap::ErrorObject(engine->syntaxErrorClass, engine->syntaxErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError) { } Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const ValueRef message) - : Heap::ErrorObject(engine->evalErrorClass, message, EvalError) + : Heap::ErrorObject(engine->evalErrorClass, engine->evalErrorPrototype.asObject(), message, EvalError) { } Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const ValueRef message) - : Heap::ErrorObject(engine->rangeErrorClass, message, RangeError) + : Heap::ErrorObject(engine->rangeErrorClass, engine->rangeErrorPrototype.asObject(), message, RangeError) { } Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message) - : Heap::ErrorObject(engine->rangeErrorClass, message, RangeError) + : Heap::ErrorObject(engine->rangeErrorClass, engine->rangeErrorPrototype.asObject(), message, RangeError) { } Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message) - : Heap::ErrorObject(engine->referenceErrorClass, message, ReferenceError) + : Heap::ErrorObject(engine->referenceErrorClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError) { } Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message) - : Heap::ErrorObject(engine->referenceErrorClass, message, ReferenceError) + : Heap::ErrorObject(engine->referenceErrorClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError) { } Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(engine->referenceErrorClass, msg, fileName, lineNumber, columnNumber, ReferenceError) + : Heap::ErrorObject(engine->referenceErrorClass, engine->referenceErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, ReferenceError) { } Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const ValueRef message) - : Heap::ErrorObject(engine->typeErrorClass, message, TypeError) + : Heap::ErrorObject(engine->typeErrorClass, engine->typeErrorPrototype.asObject(), message, TypeError) { } Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message) - : Heap::ErrorObject(engine->typeErrorClass, message, TypeError) + : Heap::ErrorObject(engine->typeErrorClass, engine->typeErrorPrototype.asObject(), message, TypeError) { } Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const ValueRef message) - : Heap::ErrorObject(engine->uriErrorClass, message, URIError) + : Heap::ErrorObject(engine->uriErrorClass, engine->uRIErrorPrototype.asObject(), message, URIError) { } diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 589d466429..71a811c189 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -55,10 +55,10 @@ struct ErrorObject : Object { URIError }; - ErrorObject(InternalClass *ic); - ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t = Error); - ErrorObject(InternalClass *ic, const QString &message, ErrorType t = Error); - ErrorObject(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error); + ErrorObject(InternalClass *ic, QV4::Object *prototype); + ErrorObject(InternalClass *ic, QV4::Object *prototype, const ValueRef message, ErrorType t = Error); + ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorType t = Error); + ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error); StackTrace stackTrace; String *stack; }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 22ed62cf18..42e0f5389d 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -63,7 +63,7 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) - : Heap::Object(scope->d()->engine->functionClass) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) { Scope s(scope->engine()); @@ -72,7 +72,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String * } Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto) - : Heap::Object(scope->d()->engine->functionClass) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) { Scope s(scope->engine()); @@ -82,7 +82,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun } Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto) - : Heap::Object(scope->d()->engine->functionClass) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) { Scope s(scope->engine()); @@ -92,7 +92,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString } Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) - : Heap::Object(scope->engine->functionClass) + : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject()) , scope(scope) { Scope s(scope->engine); @@ -102,7 +102,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam } Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name) - : Heap::Object(scope->d()->engine->functionClass) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) { Scope s(scope); @@ -112,7 +112,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne } Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name) - : Heap::Object(scope->engine->functionClass) + : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject()) , scope(scope) { Scope s(scope->engine); @@ -121,8 +121,8 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu f->init(n.getPointer(), false); } -Heap::FunctionObject::FunctionObject(InternalClass *ic) - : Heap::Object(ic) +Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype) + : Heap::Object(ic, prototype) , scope(ic->engine->rootContext()->d()) { Scope scope(ic->engine); @@ -148,7 +148,7 @@ void FunctionObject::init(String *n, bool createProto) ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype); if (createProto) { - Scoped<Object> proto(s, scope()->engine->newObject(scope()->engine->protoClass)); + Scoped<Object> proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype.asObject())); proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor); proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue(); memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue(); @@ -268,8 +268,8 @@ ReturnedValue FunctionCtor::call(Managed *that, CallData *callData) DEFINE_OBJECT_VTABLE(FunctionPrototype); -Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic) - : Heap::FunctionObject(ic) +Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype) + : Heap::FunctionObject(ic, prototype) { } @@ -393,8 +393,9 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) Scope scope(v4); Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that)); - InternalClass *ic = f->internalClassForConstructor(); - ScopedObject obj(scope, v4->newObject(ic)); + InternalClass *ic = scope.engine->objectClass; + ScopedObject proto(scope, f->protoForConstructor()); + ScopedObject obj(scope, v4->newObject(ic, proto)); ExecutionContext *context = v4->currentContext(); callData->thisObject = obj.asReturnedValue(); @@ -477,8 +478,9 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) Scope scope(v4); Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that)); - InternalClass *ic = f->internalClassForConstructor(); - callData->thisObject = v4->newObject(ic); + InternalClass *ic = scope.engine->objectClass; + ScopedObject proto(scope, f->protoForConstructor()); + callData->thisObject = v4->newObject(ic, proto); ExecutionContext *context = v4->currentContext(); ExecutionContextSaver ctxSaver(context); @@ -542,18 +544,13 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) return result.asReturnedValue(); } -InternalClass *SimpleScriptFunction::internalClassForConstructor() +Heap::Object *SimpleScriptFunction::protoForConstructor() { - ReturnedValue proto = protoProperty(); - InternalClass *classForConstructor; - Scope scope(internalClass()->engine); - ScopedObject p(scope, proto); + Scope scope(engine()); + ScopedObject p(scope, protoProperty()); if (p) - classForConstructor = internalClass()->engine->constructClass->changePrototype(p.getPointer()); - else - classForConstructor = scope.engine->objectClass; - - return classForConstructor; + return p->d(); + return scope.engine->objectPrototype.asObject()->d(); } diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 711b16a498..5d2715fa2f 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -63,7 +63,7 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name); FunctionObject(ExecutionContext *scope, const ReturnedValue name); - FunctionObject(InternalClass *ic); + FunctionObject(InternalClass *ic, QV4::Object *prototype); ~FunctionObject(); unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; } @@ -78,7 +78,7 @@ struct FunctionCtor : FunctionObject { }; struct FunctionPrototype : FunctionObject { - FunctionPrototype(InternalClass *ic); + FunctionPrototype(InternalClass *ic, QV4::Object *prototype); }; struct Q_QML_EXPORT BuiltinFunction : FunctionObject { @@ -213,7 +213,7 @@ struct SimpleScriptFunction: FunctionObject { static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); - InternalClass *internalClassForConstructor(); + Heap::Object *protoForConstructor(); }; struct ScriptFunction: SimpleScriptFunction { diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index d3e6bdd57b..0f88dd4d5a 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -42,9 +42,9 @@ QT_BEGIN_NAMESPACE uint QV4::qHash(const QV4::InternalClassTransition &t, uint) { - if (t.flags == QV4::InternalClassTransition::ProtoChange) + if (t.flags & QV4::InternalClassTransition::VTableChange) // INT_MAX is prime, so this should give a decent distribution of keys - return (uint)((quintptr)t.prototype * INT_MAX); + return (uint)((quintptr)t.vtable * INT_MAX); return t.id->hashValue ^ t.flags; } @@ -120,7 +120,6 @@ uint PropertyHash::lookup(const Identifier *identifier) const InternalClass::InternalClass(ExecutionEngine *engine) : engine(engine) - , prototype(0) , vtable(&QV4::Managed::static_vtbl) , m_sealed(0) , m_frozen(0) @@ -132,7 +131,6 @@ InternalClass::InternalClass(ExecutionEngine *engine) InternalClass::InternalClass(const QV4::InternalClass &other) : QQmlJS::Managed() , engine(other.engine) - , prototype(other.prototype) , vtable(other.vtable) , propertyTable(other.propertyTable) , nameMap(other.nameMap) @@ -180,7 +178,6 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri // create a new class and add it to the tree InternalClass *newClass = engine->emptyClass->changeVTable(vtable); - newClass = newClass->changePrototype(prototype); for (uint i = 0; i < size; ++i) { if (i == idx) { newClass = newClass->addMember(nameMap.at(i), data); @@ -193,43 +190,9 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri return newClass; } -InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto) +InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable) { - InternalClass *c = engine->emptyClass->changeVTable(vtable); - if (!proto) - return c; - return c->changePrototype(proto); -} - -InternalClass *InternalClass::changePrototype(Object *proto) -{ - if (prototype == proto) - return this; - - Transition t; - t.prototype = proto; - t.flags = Transition::ProtoChange; - - 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 (!size) { - newClass = engine->newClass(*this); - newClass->prototype = proto; - } else { - newClass = engine->emptyClass->changeVTable(vtable); - newClass = newClass->changePrototype(proto); - for (uint i = 0; i < size; ++i) { - if (!propertyData.at(i).isEmpty()) - newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); - } - } - - transitions.insert(t, newClass); - return newClass; + return engine->emptyClass->changeVTable(vtable); } InternalClass *InternalClass::changeVTable(const ManagedVTable *vt) @@ -252,7 +215,6 @@ InternalClass *InternalClass::changeVTable(const ManagedVTable *vt) newClass->vtable = vt; } else { newClass = engine->emptyClass->changeVTable(vt); - newClass = newClass->changePrototype(prototype); for (uint i = 0; i < size; ++i) { if (!propertyData.at(i).isEmpty()) newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); @@ -340,7 +302,6 @@ void InternalClass::removeMember(Object *object, Identifier *id) } else { // create a new class and add it to the tree InternalClass *newClass = oldClass->engine->emptyClass->changeVTable(oldClass->vtable); - newClass = newClass->changePrototype(oldClass->prototype); for (uint i = 0; i < oldClass->size; ++i) { if (i == propIdx) continue; @@ -384,7 +345,6 @@ InternalClass *InternalClass::sealed() m_sealed = engine->emptyClass; m_sealed = m_sealed->changeVTable(vtable); - m_sealed = m_sealed->changePrototype(prototype); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); if (attrs.isEmpty()) @@ -404,7 +364,6 @@ InternalClass *InternalClass::frozen() m_frozen = engine->emptyClass; m_frozen = m_frozen->changeVTable(vtable); - m_frozen = m_frozen->changePrototype(prototype); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); if (attrs.isEmpty()) @@ -441,24 +400,9 @@ void InternalClass::destroy() } } -struct InternalClassPoolVisitor -{ - ExecutionEngine *engine; - void operator()(InternalClass *klass) - { - // all prototype changes are done on the empty class - Q_ASSERT(!klass->prototype || klass != engine->emptyClass); - - if (klass->prototype) - klass->prototype->mark(engine); - } -}; - void InternalClassPool::markObjects(ExecutionEngine *engine) { - InternalClassPoolVisitor v; - v.engine = engine; - visitManagedPool<InternalClass, InternalClassPoolVisitor>(v); + Q_UNUSED(engine); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 14dbbe713f..4367f6576d 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -191,14 +191,12 @@ struct InternalClassTransition { union { Identifier *id; - Object *prototype; const ManagedVTable *vtable; }; int flags; enum { // range 0-0xff is reserved for attribute changes - ProtoChange = 0x100, - VTableChange = 0x200 + VTableChange = 0x100 }; bool operator==(const InternalClassTransition &other) const @@ -208,7 +206,6 @@ uint qHash(const QV4::InternalClassTransition &t, uint = 0); struct InternalClass : public QQmlJS::Managed { ExecutionEngine *engine; - Object *prototype; const ManagedVTable *vtable; PropertyHash propertyTable; // id to valueIndex @@ -223,8 +220,7 @@ struct InternalClass : public QQmlJS::Managed { uint size; - static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto); - InternalClass *changePrototype(Object *proto); + static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable); InternalClass *changeVTable(const ManagedVTable *vt); static void addMember(Object *object, String *string, PropertyAttributes data, uint *index); InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 76bc757a8c..c4a8ac13b9 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -877,10 +877,10 @@ QString Stringify::JA(ArrayObject *a) } -Heap::JsonObject::JsonObject(InternalClass *ic) - : Heap::Object(ic) +Heap::JsonObject::JsonObject(ExecutionEngine *e) + : Heap::Object(QV4::InternalClass::create(e, QV4::JsonObject::staticVTable()), e->objectPrototype.asObject()) { - Scope scope(ic->engine); + Scope scope(e); ScopedObject o(scope, this); o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2); diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index e1202095a9..4004a06dec 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -45,7 +45,7 @@ namespace QV4 { namespace Heap { struct JsonObject : Object { - JsonObject(InternalClass *ic); + JsonObject(ExecutionEngine *e); }; } diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index e6f997d5df..ebdc7be200 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -243,11 +243,11 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va case Value::Null_Type: return engine->throwTypeError(); case Value::Boolean_Type: - proto = engine->booleanClass->prototype; + proto = engine->booleanPrototype.asObject(); break; case Value::Managed_Type: { Q_ASSERT(object->isString()); - proto = engine->stringObjectClass->prototype; + proto = engine->stringPrototype.asObject(); Scope scope(engine); ScopedString name(scope, engine->currentContext()->d()->compilationUnit->runtimeStrings[l->nameIndex]); if (name->equals(engine->id_length.getPointer())) { @@ -259,7 +259,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va } case Value::Integer_Type: default: // Number - proto = engine->numberClass->prototype; + proto = engine->numberPrototype.asObject(); } PropertyAttributes attrs; diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 65302cd804..222a6fd97c 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -47,10 +47,10 @@ DEFINE_OBJECT_VTABLE(MathObject); static const double qt_PI = 2.0 * ::asin(1.0); -Heap::MathObject::MathObject(InternalClass *ic) - : Heap::Object(ic) +Heap::MathObject::MathObject(ExecutionEngine *e) + : Heap::Object(QV4::InternalClass::create(e, QV4::MathObject::staticVTable()), e->objectPrototype.asObject()) { - Scope scope(ic->engine); + Scope scope(e); ScopedObject m(scope, this); m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0))); diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index 1ff5e5a081..feff968a17 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -42,7 +42,7 @@ namespace QV4 { namespace Heap { struct MathObject : Object { - MathObject(InternalClass *ic); + MathObject(ExecutionEngine *e); }; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index a9ce9b42f2..70152274e4 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -50,8 +50,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(Object); -Heap::Object::Object(InternalClass *internalClass) - : Heap::Base(internalClass) +Heap::Object::Object(InternalClass *internalClass, QV4::Object *prototype) + : Heap::Base(internalClass), + prototype(prototype->d()) { if (internalClass->size) { Scope scope(internalClass->engine); @@ -62,13 +63,13 @@ Heap::Object::Object(InternalClass *internalClass) bool Object::setPrototype(Object *proto) { - Object *pp = proto; + Heap::Object *pp = proto->d(); while (pp) { - if (pp == this) + if (pp == d()) return false; - pp = pp->prototype(); + pp = pp->prototype; } - setInternalClass(internalClass()->changePrototype(proto)); + d()->prototype = proto->d(); return true; } @@ -187,6 +188,8 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e) o->memberData->mark(e); if (o->arrayData) o->arrayData->mark(e); + if (o->prototype) + o->prototype->mark(e); } void Object::ensureMemberIndex(uint idx) @@ -1135,7 +1138,7 @@ void Object::initSparseArray() DEFINE_OBJECT_VTABLE(ArrayObject); Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) - : Heap::Object(engine->arrayClass) + : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject()) { init(); Scope scope(engine); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 379ff2fde6..fed05893ca 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -45,47 +45,17 @@ namespace Heap { struct Object : Base { Object(ExecutionEngine *engine) - : Base(engine->objectClass) + : Base(engine->objectClass), + prototype(static_cast<Object *>(engine->objectPrototype.m)) { } - Object(InternalClass *internal = 0); + Object(InternalClass *internal, QV4::Object *prototype); + Heap::Object *prototype; MemberData *memberData; ArrayData *arrayData; }; -struct BooleanObject : Object { - BooleanObject(ExecutionEngine *engine, const ValueRef val) - : Object(engine->booleanClass) - { - value = val; - } - inline BooleanObject(InternalClass *ic); - Value value; -}; - -struct NumberObject : Object { - NumberObject(ExecutionEngine *engine, const ValueRef val) - : Object(engine->numberClass) { - value = val; - } - inline NumberObject(InternalClass *ic); - Value value; -}; - -struct ArrayObject : Object { - enum { - LengthPropertyIndex = 0 - }; - - ArrayObject(ExecutionEngine *engine) : Heap::Object(engine->arrayClass) { init(); } - ArrayObject(ExecutionEngine *engine, const QStringList &list); - ArrayObject(InternalClass *ic) : Heap::Object(ic) { init(); } - void init() - { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); } -}; - - } struct Q_QML_EXPORT Object: Managed { @@ -105,7 +75,8 @@ struct Q_QML_EXPORT Object: Managed { Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData()->data + index); } const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass()->vtable); } - Object *prototype() const { return internalClass()->prototype; } + // ### GC + Object *prototype() const { return reinterpret_cast<Object *>(d()->prototype); } bool setPrototype(Object *proto); Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0); @@ -294,6 +265,56 @@ private: friend struct ObjectPrototype; }; +namespace Heap { + +struct BooleanObject : Object { + BooleanObject(InternalClass *ic, QV4::Object *prototype) + : Object(ic, prototype) + { + value = Encode((bool)false); + } + + BooleanObject(ExecutionEngine *engine, const ValueRef val) + : Object(engine->booleanClass, engine->booleanPrototype.asObject()) + { + value = val; + } + Value value; +}; + +struct NumberObject : Object { + NumberObject(InternalClass *ic, QV4::Object *prototype) + : Object(ic, prototype) + { + value = Encode((int)0); + } + + NumberObject(ExecutionEngine *engine, const ValueRef val) + : Object(engine->numberClass, engine->numberPrototype.asObject()) + { + value = val; + } + Value value; +}; + +struct ArrayObject : Object { + enum { + LengthPropertyIndex = 0 + }; + + ArrayObject(ExecutionEngine *engine) + : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject()) + { init(); } + ArrayObject(ExecutionEngine *engine, const QStringList &list); + ArrayObject(InternalClass *ic, QV4::Object *prototype) + : Heap::Object(ic, prototype) + { init(); } + void init() + { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); } +}; + +} + struct BooleanObject: Object { V4_OBJECT2(BooleanObject, Object) Q_MANAGED_TYPE(BooleanObject) @@ -302,13 +323,6 @@ struct BooleanObject: Object { }; -Heap::BooleanObject::BooleanObject(InternalClass *ic) - : Heap::Object(ic) -{ - Q_ASSERT(internalClass->vtable == QV4::BooleanObject::staticVTable()); - value = Encode(false); -} - struct NumberObject: Object { V4_OBJECT2(NumberObject, Object) Q_MANAGED_TYPE(NumberObject) @@ -316,12 +330,6 @@ struct NumberObject: Object { Value value() const { return d()->value; } }; -Heap::NumberObject::NumberObject(InternalClass *ic) - : Heap::Object(ic) { - Q_ASSERT(internalClass->vtable == QV4::NumberObject::staticVTable()); - value = Encode((int)0); -} - struct ArrayObject: Object { V4_OBJECT2(ArrayObject, Object) Q_MANAGED_TYPE(ArrayObject) diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 3744d5617c..23d5115c6d 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -242,8 +242,8 @@ Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object) void QObjectWrapper::initializeBindings(ExecutionEngine *engine) { - engine->functionClass->prototype->defineDefaultProperty(QStringLiteral("connect"), method_connect); - engine->functionClass->prototype->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect); + engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect); + engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect); } QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const @@ -345,8 +345,8 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect"))); QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect"))); - handler->put(connect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(connect.getPointer()))); - handler->put(disconnect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(disconnect.getPointer()))); + handler->put(connect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect.getPointer()))); + handler->put(disconnect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(disconnect.getPointer()))); return handler.asReturnedValue(); } else { diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 7758cd8483..7191a16235 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -65,8 +65,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(RegExpObject); DEFINE_OBJECT_VTABLE(RegExpPrototype); -Heap::RegExpObject::RegExpObject(InternalClass *ic) - : Heap::Object(ic) +Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype) + : Heap::Object(ic, prototype) { setVTable(QV4::RegExpObject::staticVTable()); @@ -78,7 +78,7 @@ Heap::RegExpObject::RegExpObject(InternalClass *ic) } Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global) - : Heap::Object(engine->regExpClass) + : Heap::Object(engine->regExpClass, engine->regExpPrototype.asObject()) , value(value->d()) , global(global) { @@ -93,7 +93,7 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *valu // The conversion is not 100% exact since ECMA regexp and QRegExp // have different semantics/flags, but we try to do our best. Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re) - : Heap::Object(engine->regExpClass) + : Heap::Object(engine->regExpClass, engine->regExpPrototype.asObject()) { setVTable(QV4::RegExpObject::staticVTable()); @@ -380,7 +380,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) } // fill in result data - Scoped<ArrayObject> array(scope, ctx->d()->engine->newArrayObject(ctx->d()->engine->regExpExecArrayClass)); + Scoped<ArrayObject> array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject())); int len = r->value()->captureCount(); array->arrayReserve(len); ScopedValue v(scope); diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index febd0dd7b2..1320527fe1 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -57,9 +57,9 @@ namespace QV4 { namespace Heap { struct RegExpObject : Object { + RegExpObject(InternalClass *ic, QV4::Object *prototype); RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global); RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re); - RegExpObject(InternalClass *ic); RegExp *value; bool global; @@ -76,7 +76,7 @@ struct RegExpCtor : FunctionObject { struct RegExpPrototype : RegExpObject { - inline RegExpPrototype(InternalClass *ic); + inline RegExpPrototype(ExecutionEngine *e); }; } @@ -145,10 +145,9 @@ struct RegExpPrototype: RegExpObject static ReturnedValue method_get_rightContext(CallContext *ctx); }; -inline Heap::RegExpPrototype::RegExpPrototype(InternalClass *ic) - : RegExpObject(ic) +inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e) + : RegExpObject(InternalClass::create(e, QV4::RegExpPrototype::staticVTable()), e->objectPrototype.asObject()) { - setVTable(QV4::RegExpPrototype::staticVTable()); } } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 147e81b627..5d9eb6d55e 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1187,7 +1187,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value * { Scope scope(engine); QV4::InternalClass *klass = engine->currentContext()->d()->compilationUnit->runtimeClasses[classId]; - Scoped<Object> o(scope, engine->newObject(klass)); + Scoped<Object> o(scope, engine->newObject(klass, engine->objectPrototype.asObject())); { bool needSparseArray = arrayGetterSetterCountAndFlags >> 30; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 20dad8a6d6..5e45f65ae7 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -500,7 +500,7 @@ public: template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container) - : Heap::Object(InternalClass::create(engine, QV4::QQmlSequence<Container>::staticVTable(), engine->sequencePrototype.asObject())) + : Heap::Object(InternalClass::create(engine, QV4::QQmlSequence<Container>::staticVTable()), engine->sequencePrototype.asObject()) , container(container) , propertyIndex(-1) , isReference(false) @@ -513,7 +513,7 @@ Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex) - : Heap::Object(InternalClass::create(engine, QV4::QQmlSequence<Container>::staticVTable(), engine->sequencePrototype.asObject())) + : Heap::Object(InternalClass::create(engine, QV4::QQmlSequence<Container>::staticVTable()), engine->sequencePrototype.asObject()) , object(object) , propertyIndex(propertyIndex) , isReference(true) diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 5c020ddc8e..e6a7a2f7a7 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -138,7 +138,7 @@ ReturnedValue String::get(Managed *m, String *name, bool *hasProperty) return Primitive::fromInt32(that->d()->text->size).asReturnedValue(); } PropertyAttributes attrs; - Property *pd = v4->stringObjectClass->prototype->__getPropertyDescriptor__(name, &attrs); + Property *pd = v4->stringPrototype.asObject()->__getPropertyDescriptor__(name, &attrs); if (!pd || attrs.isGeneric()) { if (hasProperty) *hasProperty = false; @@ -146,7 +146,7 @@ ReturnedValue String::get(Managed *m, String *name, bool *hasProperty) } if (hasProperty) *hasProperty = true; - return v4->stringObjectClass->prototype->getValue(that, pd, attrs); + return v4->stringPrototype.asObject()->getValue(that, pd, attrs); } ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty) @@ -161,7 +161,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty) return Encode(engine->newString(that->toQString().mid(index, 1))); } PropertyAttributes attrs; - Property *pd = engine->stringObjectClass->prototype->__getPropertyDescriptor__(index, &attrs); + Property *pd = engine->stringPrototype.asObject()->__getPropertyDescriptor__(index, &attrs); if (!pd || attrs.isGeneric()) { if (hasProperty) *hasProperty = false; @@ -169,7 +169,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty) } if (hasProperty) *hasProperty = true; - return engine->stringObjectClass->prototype->getValue(that, pd, attrs); + return engine->stringPrototype.asObject()->getValue(that, pd, attrs); } void String::put(Managed *m, String *name, const ValueRef value) diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index ed29c84ff9..8c864803af 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -70,8 +70,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(StringObject); -Heap::StringObject::StringObject(InternalClass *ic) - : Heap::Object(ic) +Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype) + : Heap::Object(ic, prototype) { Q_ASSERT(internalClass->vtable == QV4::StringObject::staticVTable()); value = ic->engine->newString(QStringLiteral(""))->asReturnedValue(); @@ -83,7 +83,7 @@ Heap::StringObject::StringObject(InternalClass *ic) } Heap::StringObject::StringObject(ExecutionEngine *engine, const ValueRef val) - : Heap::Object(engine->stringObjectClass) + : Heap::Object(engine->stringObjectClass, engine->stringPrototype.asObject()) { value = val; Q_ASSERT(value.isString()); @@ -386,8 +386,8 @@ ReturnedValue StringPrototype::method_match(CallContext *context) bool global = rx->global(); // ### use the standard builtin function, not the one that might be redefined in the proto - ScopedString execString(scope, context->d()->engine->newString(QStringLiteral("exec"))); - Scoped<FunctionObject> exec(scope, context->d()->engine->regExpClass->prototype->get(execString.getPointer())); + ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec"))); + Scoped<FunctionObject> exec(scope, scope.engine->regExpPrototype.asObject()->get(execString.getPointer())); ScopedCallData callData(scope, 1); callData->thisObject = rx; diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index b82cf08a8b..031b09c093 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -44,8 +44,8 @@ namespace QV4 { namespace Heap { struct StringObject : Object { + StringObject(InternalClass *ic, QV4::Object *prototype); StringObject(ExecutionEngine *engine, const ValueRef value); - StringObject(InternalClass *ic); Value value; // ### get rid of tmpProperty mutable Property tmpProperty; diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 3149e0485a..cc5ea2aad5 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -334,7 +334,7 @@ ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData) } Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t) - : Heap::Object(e->typedArrayClasses[t]), + : Heap::Object(e->typedArrayClasses[t], e->typedArrayPrototype[t].asObject()), type(operations + t) { } diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index fe23b8aa15..3e659eec5a 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -43,13 +43,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(VariantObject); -Heap::VariantObject::VariantObject(InternalClass *ic) - : Heap::Object(ic) -{ -} - Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value) - : Heap::Object(engine->variantClass) + : Heap::Object(engine->variantClass, engine->variantPrototype.asObject()) { data = value; if (isScarce()) diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index c231db44a6..14ef167e6f 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -60,7 +60,9 @@ namespace Heap { struct VariantObject : Object, public ExecutionEngine::ScarceResourceData { - VariantObject(InternalClass *ic); + VariantObject(InternalClass *ic, QV4::Object *prototype) + : Object(ic, prototype) + {} VariantObject(QV4::ExecutionEngine *engine, const QVariant &value); ~VariantObject() { if (isScarce()) diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index bed6c4c57e..592318e561 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -65,9 +65,9 @@ static bool isLocaleObject(const QV4::ValueRef val) void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine) { - engine->dateClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); - engine->dateClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString); - engine->dateClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString); + engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); + engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString); + engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString); engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString); engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString); @@ -347,8 +347,8 @@ QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *c void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine) { - engine->numberClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); - engine->numberClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString); + engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); + engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString); engine->numberCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); } @@ -817,7 +817,7 @@ QV4::ReturnedValue QQmlLocale::wrap(QV8Engine *engine, const QLocale &locale) void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine) { - engine->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare); + engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare); } QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx) diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 346e745234..fc6eb50ed6 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -154,7 +154,7 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int pr initProto(v4); Scoped<QmlValueTypeReference> r(scope, v4->memoryManager->alloc<QmlValueTypeReference>(v8)); - r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype); + r->setPrototype(v4->qmlExtensions()->valueTypeWrapperPrototype->asObject()); r->d()->type = type; r->d()->object = object; r->d()->property = property; return r->asReturnedValue(); } @@ -166,7 +166,7 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, initProto(v4); Scoped<QmlValueTypeCopy> r(scope, v4->memoryManager->alloc<QmlValueTypeCopy>(v8)); - r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype); + r->setPrototype(v4->qmlExtensions()->valueTypeWrapperPrototype->asObject()); r->d()->type = type; r->d()->value = value; return r->asReturnedValue(); } diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index cdc76e5c97..c6e97445c0 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1587,7 +1587,7 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject) globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt); // string prototype extension - v4->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("arg"), method_string_arg); + v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg); } |