Move prototype back from the vtable into Object
authorLars Knoll <lars.knoll@digia.com>
Mon, 24 Nov 2014 14:38:41 +0000 (15:38 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Thu, 11 Dec 2014 14:52:13 +0000 (15:52 +0100)
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>
35 files changed:
src/qml/jsapi/qjsengine.cpp
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4arraybuffer.cpp
src/qml/jsruntime/qv4dataview.cpp
src/qml/jsruntime/qv4dateobject.cpp
src/qml/jsruntime/qv4dateobject_p.h
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4errorobject.cpp
src/qml/jsruntime/qv4errorobject_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4internalclass.cpp
src/qml/jsruntime/qv4internalclass_p.h
src/qml/jsruntime/qv4jsonobject.cpp
src/qml/jsruntime/qv4jsonobject_p.h
src/qml/jsruntime/qv4lookup.cpp
src/qml/jsruntime/qv4mathobject.cpp
src/qml/jsruntime/qv4mathobject_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4regexpobject.cpp
src/qml/jsruntime/qv4regexpobject_p.h
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4sequenceobject.cpp
src/qml/jsruntime/qv4string.cpp
src/qml/jsruntime/qv4stringobject.cpp
src/qml/jsruntime/qv4stringobject_p.h
src/qml/jsruntime/qv4typedarray.cpp
src/qml/jsruntime/qv4variantobject.cpp
src/qml/jsruntime/qv4variantobject_p.h
src/qml/qml/qqmllocale.cpp
src/qml/qml/qqmlvaluetypewrapper.cpp
src/qml/qml/v8/qqmlbuiltinfunctions.cpp

index bd78b7d..e25d166 100644 (file)
@@ -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);
index 78c8d6f..d283537 100644 (file)
@@ -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)
 {
index b8b9971..9fc3114 100644 (file)
@@ -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) {
index 61a0091..36d597f 100644 (file)
@@ -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)
index c5d25e4..811d2f0 100644 (file)
@@ -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());
index 4eba963..b164de6 100644 (file)
@@ -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)
index ddee344..160dbe4 100644 (file)
@@ -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);
index ad9fde3..dc75d37 100644 (file)
@@ -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);
index 7fe0574..d08619f 100644 (file)
@@ -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)
 {
 }
 
index 589d466..71a811c 100644 (file)
@@ -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;
 };
index 22ed62c..42e0f53 100644 (file)
@@ -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();
 }
 
 
index 711b16a..5d2715f 100644 (file)
@@ -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 {
index d3e6bdd..0f88dd4 100644 (file)
@@ -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
index 14dbbe7..4367f65 100644 (file)
@@ -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);
index 76bc757..c4a8ac1 100644 (file)
@@ -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);
index e120209..4004a06 100644 (file)
@@ -45,7 +45,7 @@ namespace QV4 {
 namespace Heap {
 
 struct JsonObject : Object {
-    JsonObject(InternalClass *ic);
+    JsonObject(ExecutionEngine *e);
 };
 
 }
index e6f997d..ebdc7be 100644 (file)
@@ -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;
index 65302cd..222a6fd 100644 (file)
@@ -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)));
index 1ff5e5a..feff968 100644 (file)
@@ -42,7 +42,7 @@ namespace QV4 {
 namespace Heap {
 
 struct MathObject : Object {
-    MathObject(InternalClass *ic);
+    MathObject(ExecutionEngine *e);
 };
 
 }
index a9ce9b4..7015227 100644 (file)
@@ -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);
index 379ff2f..fed0589 100644 (file)
@@ -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)
index 3744d56..23d5115 100644 (file)
@@ -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 {
index 7758cd8..7191a16 100644 (file)
@@ -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);
index febd0dd..1320527 100644 (file)
@@ -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());
 }
 
 }
index 147e81b..5d9eb6d 100644 (file)
@@ -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;
index 20dad8a..5e45f65 100644 (file)
@@ -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)
index 5c020dd..e6a7a2f 100644 (file)
@@ -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)
index ed29c84..8c86480 100644 (file)
@@ -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;
index b82cf08..031b09c 100644 (file)
@@ -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;
index 3149e04..cc5ea2a 100644 (file)
@@ -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)
 {
 }
index fe23b8a..3e659ee 100644 (file)
@@ -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())
index c231db4..14ef167 100644 (file)
@@ -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())
index bed6c4c..592318e 100644 (file)
@@ -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)
index 346e745..fc6eb50 100644 (file)
@@ -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();
 }
index cdc76e5..c6e9744 100644 (file)
@@ -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);
 }