Move prototype pointer into QV4::InternalClass
authorLars Knoll <lars.knoll@digia.com>
Thu, 29 Aug 2013 12:31:32 +0000 (14:31 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 2 Sep 2013 15:27:36 +0000 (17:27 +0200)
The prototype is actually the same for most objects. By
moving it into the internal class, we can save 8 bytes
per object, as well as allowing for some future
optimizations.

Also fix a bug in the implementation of the Error
prototype objects.

Change-Id: I4d4b641055f644a9b088f27be34bfdb0446279b7
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
48 files changed:
src/imports/localstorage/plugin.cpp
src/particles/qquickv4particledata.cpp
src/qml/compiler/qv4compileddata.cpp
src/qml/jsapi/qjsvalue.cpp
src/qml/jsruntime/qv4arrayobject.cpp
src/qml/jsruntime/qv4arrayobject_p.h
src/qml/jsruntime/qv4booleanobject_p.h
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/qv4jsonobject.cpp
src/qml/jsruntime/qv4lookup.cpp
src/qml/jsruntime/qv4mathobject.cpp
src/qml/jsruntime/qv4numberobject_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4objectiterator.cpp
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4objectproto_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/qv4sequenceobject_p.h
src/qml/jsruntime/qv4stringobject.cpp
src/qml/jsruntime/qv4stringobject_p.h
src/qml/jsruntime/qv4variantobject.cpp
src/qml/jsruntime/qv4variantobject_p.h
src/qml/qml/qqmlcomponent.cpp
src/qml/qml/qqmlcontextwrapper.cpp
src/qml/qml/qqmllistwrapper.cpp
src/qml/qml/qqmllocale.cpp
src/qml/qml/qqmltypewrapper.cpp
src/qml/qml/qqmlvaluetypewrapper.cpp
src/qml/qml/qqmlxmlhttprequest.cpp
src/qml/qml/v8/qqmlbuiltinfunctions.cpp
src/qml/qml/v8/qv8engine.cpp
src/qml/types/qqmldelegatemodel.cpp
src/qml/util/qqmladaptormodel.cpp
src/quick/items/context2d/qquickcontext2d.cpp
tests/manual/v4/TestExpectations
tools/v4/main.cpp

index 6fc7d1d..7c7303a 100644 (file)
@@ -99,7 +99,7 @@ public:
         : Object(QV8Engine::getV4(e)), type(Database), inTransaction(false), readonly(false), forwardOnly(false)
     {
         vtbl = &static_vtbl;
-        prototype = QV8Engine::getV4(e)->objectPrototype;
+        setPrototype(QV8Engine::getV4(e)->objectPrototype);
     }
 
     ~QQmlSqlDatabaseWrapper() {
@@ -287,7 +287,7 @@ static Value qmlsqldatabase_executeSql(SimpleCallContext *ctx)
         }
         if (query.exec()) {
             QQmlSqlDatabaseWrapper *rows = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine);
-            rows->prototype = databaseData(engine)->rowsProto.value().asObject();
+            rows->setPrototype(databaseData(engine)->rowsProto.value().asObject());
             rows->type = QQmlSqlDatabaseWrapper::Rows;
             rows->database = db;
             rows->sqlQuery = query;
@@ -330,7 +330,7 @@ static Value qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
         V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version));
 
     QQmlSqlDatabaseWrapper *w = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine);
-    w->prototype = databaseData(engine)->queryProto.value().asObject();
+    w->setPrototype(databaseData(engine)->queryProto.value().asObject());
     w->type = QQmlSqlDatabaseWrapper::Query;
     w->database = db;
     w->version = r->version;
@@ -386,7 +386,7 @@ static Value qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, bool read
     QSqlDatabase db = r->database;
 
     QQmlSqlDatabaseWrapper *w = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine);
-    w->prototype = databaseData(engine)->queryProto.value().asObject();
+    w->setPrototype(databaseData(engine)->queryProto.value().asObject());
     w->type = QQmlSqlDatabaseWrapper::Query;
     w->database = db;
     w->version = r->version;
@@ -673,7 +673,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
     }
 
     QQmlSqlDatabaseWrapper *db = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine);
-    db->prototype = databaseData(engine)->databaseProto.value().asObject();
+    db->setPrototype(databaseData(engine)->databaseProto.value().asObject());
     db->database = database;
     db->version = version;
 
index a5ec20a..2cb95b4 100644 (file)
@@ -503,7 +503,7 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData
     QV8ParticleDataDeletable *d = particleV8Data(engine);
     QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
     QV4::Object *o = new (v4->memoryManager) QV4ParticleData(v4, datum);
-    o->prototype = d->proto.value().asObject();
+    o->setPrototype(d->proto.value().asObject());
     m_v4Value = QV4::Value::fromObject(o);
 }
 
index 4c1b05b..696531f 100644 (file)
@@ -43,6 +43,7 @@
 #include "qv4jsir_p.h"
 #include <private/qv4engine_p.h>
 #include <private/qv4function_p.h>
+#include <private/qv4objectproto_p.h>
 #include <private/qv4lookup_p.h>
 #include <private/qv4regexpobject_p.h>
 #include <private/qv4unwindhelper_p.h>
@@ -124,6 +125,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
             int memberCount = 0;
             const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
             QV4::InternalClass *klass = engine->emptyClass;
+            klass = klass->changePrototype(engine->objectPrototype);
             for (int j = 0; j < memberCount; ++j, ++member)
                 klass = klass->addMember(runtimeStrings[member->nameOffset], member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
 
index cff760b..b737ee0 100644 (file)
@@ -662,9 +662,9 @@ QJSValue QJSValue::prototype() const
     Object *o = d->value.asObject();
     if (!o)
         return QJSValue();
-    if (!o->prototype)
+    if (!o->prototype())
         return QJSValue(NullValue);
-    return new QJSValuePrivate(o->internalClass->engine, Value::fromObject(o->prototype));
+    return new QJSValuePrivate(o->internalClass->engine, Value::fromObject(o->prototype()));
 }
 
 /*!
@@ -685,7 +685,7 @@ void QJSValue::setPrototype(const QJSValue& prototype)
     if (!o)
         return;
     if (prototype.d->value.isNull()) {
-        o->prototype = 0;
+        o->setPrototype(0);
         return;
     }
 
@@ -696,15 +696,8 @@ void QJSValue::setPrototype(const QJSValue& prototype)
         qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
         return;
     }
-    Object *pp = p;
-    while (pp) {
-        if (pp == o) {
-            qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
-            return;
-        }
-        pp = pp->prototype;
-    }
-    o->prototype = p;
+    if (!o->setPrototype(p))
+        qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
 }
 
 /*!
index 60e7afd..6fc6615 100644 (file)
@@ -84,8 +84,8 @@ Value ArrayCtor::call(Managed *that, const CallData &d)
     return construct(that, d);
 }
 
-ArrayPrototype::ArrayPrototype(ExecutionContext *context)
-    : ArrayObject(context->engine)
+ArrayPrototype::ArrayPrototype(InternalClass *ic)
+    : ArrayObject(ic)
 {
 }
 
index f5c2566..0d76542 100644 (file)
@@ -62,7 +62,7 @@ protected:
 
 struct ArrayPrototype: ArrayObject
 {
-    ArrayPrototype(ExecutionContext *context);
+    ArrayPrototype(InternalClass *ic);
 
     void init(ExecutionContext *ctx, const Value &ctor);
 
index 0cdcdec..b55f82b 100644 (file)
@@ -62,7 +62,7 @@ protected:
 
 struct BooleanPrototype: BooleanObject
 {
-    BooleanPrototype(ExecutionEngine *engine): BooleanObject(engine, Value::fromBoolean(false)) {}
+    BooleanPrototype(InternalClass *ic): BooleanObject(ic) {}
     void init(ExecutionContext *ctx, const Value &ctor);
 
     static Value method_toString(SimpleCallContext *ctx);
index 89ca057..8c925d4 100644 (file)
@@ -53,6 +53,7 @@ namespace QV4 {
 
 struct DateObject: Object {
     Value value;
+    DateObject(InternalClass *ic): Object(ic), value(Value::fromDouble(qSNaN())) { type = Type_DateObject; }
     DateObject(ExecutionEngine *engine, const Value &value): Object(engine), value(value) { type = Type_DateObject; }
     DateObject(ExecutionEngine *engine, const QDateTime &value);
 
@@ -72,7 +73,7 @@ protected:
 
 struct DatePrototype: DateObject
 {
-    DatePrototype(ExecutionEngine *engine): DateObject(engine, Value::fromDouble(qSNaN())) {}
+    DatePrototype(InternalClass *ic): DateObject(ic) {}
     void init(ExecutionContext *ctx, const Value &ctor);
 
     static double getThisDate(ExecutionContext *ctx);
index 08093ca..00b7905 100644 (file)
@@ -136,46 +136,36 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     id_uintMax = newIdentifier(QStringLiteral("4294967295"));
     id_name = newIdentifier(QStringLiteral("name"));
 
-    arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
-    InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable);
+    objectPrototype = new (memoryManager) ObjectPrototype(emptyClass);
+    objectClass = emptyClass->changePrototype(objectPrototype);
+
+    arrayClass = objectClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
+    arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass);
+    arrayClass = arrayClass->changePrototype(arrayPrototype);
+
+    InternalClass *argsClass = objectClass->addMember(id_length, Attr_NotEnumerable);
     argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
     strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
     strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
     initRootContext();
 
-    objectPrototype = new (memoryManager) ObjectPrototype(this);
-    stringPrototype = new (memoryManager) StringPrototype(this);
-    numberPrototype = new (memoryManager) NumberPrototype(this);
-    booleanPrototype = new (memoryManager) BooleanPrototype(this);
-    arrayPrototype = new (memoryManager) ArrayPrototype(rootContext);
-    datePrototype = new (memoryManager) DatePrototype(this);
-    functionPrototype = new (memoryManager) FunctionPrototype(rootContext);
-    regExpPrototype = new (memoryManager) RegExpPrototype(this);
-    errorPrototype = new (memoryManager) ErrorPrototype(this);
-    evalErrorPrototype = new (memoryManager) EvalErrorPrototype(this);
-    rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(this);
-    referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(this);
-    syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(this);
-    typeErrorPrototype = new (memoryManager) TypeErrorPrototype(this);
-    uRIErrorPrototype = new (memoryManager) URIErrorPrototype(this);
-
-    variantPrototype = new (memoryManager) VariantPrototype(this);
-    sequencePrototype = new (memoryManager) SequencePrototype(this);
-
-    stringPrototype->prototype = objectPrototype;
-    numberPrototype->prototype = objectPrototype;
-    booleanPrototype->prototype = objectPrototype;
-    arrayPrototype->prototype = objectPrototype;
-    datePrototype->prototype = objectPrototype;
-    functionPrototype->prototype = objectPrototype;
-    regExpPrototype->prototype = objectPrototype;
-    errorPrototype->prototype = objectPrototype;
-    evalErrorPrototype->prototype = objectPrototype;
-    rangeErrorPrototype->prototype = objectPrototype;
-    referenceErrorPrototype->prototype = objectPrototype;
-    syntaxErrorPrototype->prototype = objectPrototype;
-    typeErrorPrototype->prototype = objectPrototype;
-    uRIErrorPrototype->prototype = objectPrototype;
+    stringPrototype = new (memoryManager) StringPrototype(objectClass);
+    numberPrototype = new (memoryManager) NumberPrototype(objectClass);
+    booleanPrototype = new (memoryManager) BooleanPrototype(objectClass);
+    datePrototype = new (memoryManager) DatePrototype(objectClass);
+    functionPrototype = new (memoryManager) FunctionPrototype(objectClass);
+    regExpPrototype = new (memoryManager) RegExpPrototype(objectClass);
+    errorPrototype = new (memoryManager) ErrorPrototype(objectClass);
+    InternalClass *errorProtoClass = emptyClass->changePrototype(errorPrototype);
+    evalErrorPrototype = new (memoryManager) EvalErrorPrototype(errorProtoClass);
+    rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(errorProtoClass);
+    referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(errorProtoClass);
+    syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(errorProtoClass);
+    typeErrorPrototype = new (memoryManager) TypeErrorPrototype(errorProtoClass);
+    uRIErrorPrototype = new (memoryManager) URIErrorPrototype(errorProtoClass);
+
+    variantPrototype = new (memoryManager) VariantPrototype(objectClass);
+    sequencePrototype = new (memoryManager) SequencePrototype(arrayClass->changePrototype(arrayPrototype));
 
     objectCtor = Value::fromObject(new (memoryManager) ObjectCtor(rootContext));
     stringCtor = Value::fromObject(new (memoryManager) StringCtor(rootContext));
@@ -193,21 +183,21 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     typeErrorCtor = Value::fromObject(new (memoryManager) TypeErrorCtor(rootContext));
     uRIErrorCtor = Value::fromObject(new (memoryManager) URIErrorCtor(rootContext));
 
-    objectCtor.objectValue()->prototype = functionPrototype;
-    stringCtor.objectValue()->prototype = functionPrototype;
-    numberCtor.objectValue()->prototype = functionPrototype;
-    booleanCtor.objectValue()->prototype = functionPrototype;
-    arrayCtor.objectValue()->prototype = functionPrototype;
-    functionCtor.objectValue()->prototype = functionPrototype;
-    dateCtor.objectValue()->prototype = functionPrototype;
-    regExpCtor.objectValue()->prototype = functionPrototype;
-    errorCtor.objectValue()->prototype = functionPrototype;
-    evalErrorCtor.objectValue()->prototype = functionPrototype;
-    rangeErrorCtor.objectValue()->prototype = functionPrototype;
-    referenceErrorCtor.objectValue()->prototype = functionPrototype;
-    syntaxErrorCtor.objectValue()->prototype = functionPrototype;
-    typeErrorCtor.objectValue()->prototype = functionPrototype;
-    uRIErrorCtor.objectValue()->prototype = functionPrototype;
+    objectCtor.objectValue()->setPrototype(functionPrototype);
+    stringCtor.objectValue()->setPrototype(functionPrototype);
+    numberCtor.objectValue()->setPrototype(functionPrototype);
+    booleanCtor.objectValue()->setPrototype(functionPrototype);
+    arrayCtor.objectValue()->setPrototype(functionPrototype);
+    functionCtor.objectValue()->setPrototype(functionPrototype);
+    dateCtor.objectValue()->setPrototype(functionPrototype);
+    regExpCtor.objectValue()->setPrototype(functionPrototype);
+    errorCtor.objectValue()->setPrototype(functionPrototype);
+    evalErrorCtor.objectValue()->setPrototype(functionPrototype);
+    rangeErrorCtor.objectValue()->setPrototype(functionPrototype);
+    referenceErrorCtor.objectValue()->setPrototype(functionPrototype);
+    syntaxErrorCtor.objectValue()->setPrototype(functionPrototype);
+    typeErrorCtor.objectValue()->setPrototype(functionPrototype);
+    uRIErrorCtor.objectValue()->setPrototype(functionPrototype);
 
     objectPrototype->init(rootContext, objectCtor);
     stringPrototype->init(this, stringCtor);
@@ -337,14 +327,14 @@ BoundFunction *ExecutionEngine::newBoundFunction(ExecutionContext *scope, Functi
 Object *ExecutionEngine::newObject()
 {
     Object *object = new (memoryManager) Object(this);
-    object->prototype = objectPrototype;
+    object->setPrototype(objectPrototype);
     return object;
 }
 
 Object *ExecutionEngine::newObject(InternalClass *internalClass)
 {
     Object *object = new (memoryManager) Object(internalClass);
-    object->prototype = objectPrototype;
+    object->setPrototype(objectPrototype);
     return object;
 }
 
@@ -361,28 +351,27 @@ String *ExecutionEngine::newIdentifier(const QString &text)
 Object *ExecutionEngine::newStringObject(const Value &value)
 {
     StringObject *object = new (memoryManager) StringObject(this, value);
-    object->prototype = stringPrototype;
+    object->setPrototype(stringPrototype);
     return object;
 }
 
 Object *ExecutionEngine::newNumberObject(const Value &value)
 {
     NumberObject *object = new (memoryManager) NumberObject(this, value);
-    object->prototype = numberPrototype;
+    object->setPrototype(numberPrototype);
     return object;
 }
 
 Object *ExecutionEngine::newBooleanObject(const Value &value)
 {
     Object *object = new (memoryManager) BooleanObject(this, value);
-    object->prototype = booleanPrototype;
+    object->setPrototype(booleanPrototype);
     return object;
 }
 
 ArrayObject *ExecutionEngine::newArrayObject(int count)
 {
     ArrayObject *object = new (memoryManager) ArrayObject(this);
-    object->prototype = arrayPrototype;
 
     if (count) {
         if (count < 0x1000)
@@ -395,21 +384,20 @@ ArrayObject *ExecutionEngine::newArrayObject(int count)
 ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
 {
     ArrayObject *object = new (memoryManager) ArrayObject(this, list);
-    object->prototype = arrayPrototype;
     return object;
 }
 
 DateObject *ExecutionEngine::newDateObject(const Value &value)
 {
     DateObject *object = new (memoryManager) DateObject(this, value);
-    object->prototype = datePrototype;
+    object->setPrototype(datePrototype);
     return object;
 }
 
 DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
 {
     DateObject *object = new (memoryManager) DateObject(this, dt);
-    object->prototype = datePrototype;
+    object->setPrototype(datePrototype);
     return object;
 }
 
@@ -429,21 +417,21 @@ RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags
 RegExpObject *ExecutionEngine::newRegExpObject(RegExp* re, bool global)
 {
     RegExpObject *object = new (memoryManager) RegExpObject(this, re, global);
-    object->prototype = regExpPrototype;
+    object->setPrototype(regExpPrototype);
     return object;
 }
 
 RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
 {
     RegExpObject *object = new (memoryManager) RegExpObject(this, re);
-    object->prototype = regExpPrototype;
+    object->setPrototype(regExpPrototype);
     return object;
 }
 
 Object *ExecutionEngine::newErrorObject(const Value &value)
 {
     ErrorObject *object = new (memoryManager) ErrorObject(this, value);
-    object->prototype = errorPrototype;
+    object->setPrototype(errorPrototype);
     return object;
 }
 
@@ -628,9 +616,9 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
     argumentsAccessors.resize(n);
     for (int i = oldSize; i < n; ++i) {
         FunctionObject *get = new (memoryManager) ArgumentsGetterFunction(rootContext, i);
-        get->prototype = functionPrototype;
+        get->setPrototype(functionPrototype);
         FunctionObject *set = new (memoryManager) ArgumentsSetterFunction(rootContext, i);
-        set->prototype = functionPrototype;
+        set->setPrototype(functionPrototype);
         Property pd = Property::fromAccessor(get, set);
         argumentsAccessors[i] = pd;
     }
index 8f6e47e..c368f4e 100644 (file)
@@ -170,6 +170,7 @@ struct Q_QML_EXPORT ExecutionEngine
 
     QQmlJS::MemoryPool classPool;
     InternalClass *emptyClass;
+    InternalClass *objectClass;
     InternalClass *arrayClass;
     InternalClass *argumentsObjectClass;
     InternalClass *strictArgumentsObjectClass;
index 6c7c290..f0d7d72 100644 (file)
 
 using namespace QV4;
 
+ErrorObject::ErrorObject(InternalClass *ic)
+    : Object(ic)
+    , stack(0)
+{
+    type = Type_ErrorObject;
+    vtbl = &static_vtbl;
+    defineDefaultProperty(ic->engine, QStringLiteral("name"), Value::fromString(ic->engine, "Error"));
+}
+
 ErrorObject::ErrorObject(ExecutionEngine *engine, const Value &message, ErrorType t)
     : Object(engine)
     , stack(0)
@@ -158,68 +167,68 @@ SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg)
     : ErrorObject(engine, msg, SyntaxError)
 {
     vtbl = &static_vtbl;
-    prototype = engine->syntaxErrorPrototype;
+    setPrototype(engine->syntaxErrorPrototype);
 }
 
 SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
     : ErrorObject(engine, msg, fileName, lineNumber, columnNumber, SyntaxError)
 {
     vtbl = &static_vtbl;
-    prototype = engine->syntaxErrorPrototype;
+    setPrototype(engine->syntaxErrorPrototype);
 }
 
 EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message)
     : ErrorObject(engine, message, EvalError)
 {
-    prototype = engine->evalErrorPrototype;
+    setPrototype(engine->evalErrorPrototype);
 }
 
 RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message)
     : ErrorObject(engine, message, RangeError)
 {
-    prototype = engine->rangeErrorPrototype;
+    setPrototype(engine->rangeErrorPrototype);
 }
 
 RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
     : ErrorObject(engine, Value::fromString(engine, message), RangeError)
 {
-    prototype = engine->rangeErrorPrototype;
+    setPrototype(engine->rangeErrorPrototype);
 }
 
 ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message)
     : ErrorObject(engine, message, ReferenceError)
 {
-    prototype = engine->referenceErrorPrototype;
+    setPrototype(engine->referenceErrorPrototype);
 }
 
 ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
     : ErrorObject(engine, Value::fromString(engine, message), ReferenceError)
 {
-    prototype = engine->referenceErrorPrototype;
+    setPrototype(engine->referenceErrorPrototype);
 }
 
 ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
     : ErrorObject(engine, msg, fileName, lineNumber, columnNumber, ReferenceError)
 {
-    prototype = engine->referenceErrorPrototype;
+    setPrototype(engine->referenceErrorPrototype);
 }
 
 TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message)
     : ErrorObject(engine, message, TypeError)
 {
-    prototype = engine->typeErrorPrototype;
+    setPrototype(engine->typeErrorPrototype);
 }
 
 TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
     : ErrorObject(engine, Value::fromString(engine, message), TypeError)
 {
-    prototype = engine->typeErrorPrototype;
+    setPrototype(engine->typeErrorPrototype);
 }
 
 URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message)
     : ErrorObject(engine, message, URIError)
 {
-    prototype = engine->uRIErrorPrototype;
+    setPrototype(engine->uRIErrorPrototype);
 }
 
 DEFINE_MANAGED_VTABLE(ErrorCtor);
index c510232..e7bf995 100644 (file)
@@ -63,6 +63,7 @@ struct ErrorObject: Object {
         URIError
     };
 
+    ErrorObject(InternalClass *ic);
     ErrorObject(ExecutionEngine *engine, const Value &message, ErrorType t = Error);
     ErrorObject(ExecutionEngine *engine, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
 
@@ -184,46 +185,46 @@ protected:
 struct ErrorPrototype: ErrorObject
 {
     // ### shouldn't be undefined
-    ErrorPrototype(ExecutionEngine *engine): ErrorObject(engine, Value::undefinedValue()) {}
+    ErrorPrototype(InternalClass *ic): ErrorObject(ic) {}
     void init(ExecutionEngine *engine, const Value &ctor) { init(engine, ctor, this); }
 
     static void init(ExecutionEngine *engine, const Value &ctor, Object *obj);
     static Value method_toString(SimpleCallContext *ctx);
 };
 
-struct EvalErrorPrototype: EvalErrorObject
+struct EvalErrorPrototype: ErrorObject
 {
-    EvalErrorPrototype(ExecutionEngine *engine): EvalErrorObject(engine, Value::undefinedValue()) { vtbl = &static_vtbl; }
+    EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
     void init(ExecutionEngine *engine, const Value &ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
-struct RangeErrorPrototype: RangeErrorObject
+struct RangeErrorPrototype: ErrorObject
 {
-    RangeErrorPrototype(ExecutionEngine *engine): RangeErrorObject(engine, Value::undefinedValue()) { vtbl = &static_vtbl; }
+    RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
     void init(ExecutionEngine *engine, const Value &ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
-struct ReferenceErrorPrototype: ReferenceErrorObject
+struct ReferenceErrorPrototype: ErrorObject
 {
-    ReferenceErrorPrototype(ExecutionEngine *engine): ReferenceErrorObject(engine, Value::undefinedValue()) { vtbl = &static_vtbl; }
+    ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
     void init(ExecutionEngine *engine, const Value &ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
-struct SyntaxErrorPrototype: SyntaxErrorObject
+struct SyntaxErrorPrototype: ErrorObject
 {
-    SyntaxErrorPrototype(ExecutionEngine *engine): SyntaxErrorObject(engine, Value::undefinedValue()) { vtbl = &static_vtbl; }
+    SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
     void init(ExecutionEngine *engine, const Value &ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
-struct TypeErrorPrototype: TypeErrorObject
+struct TypeErrorPrototype: ErrorObject
 {
-    TypeErrorPrototype(ExecutionEngine *engine): TypeErrorObject(engine, Value::undefinedValue()) { vtbl = &static_vtbl; }
+    TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
     void init(ExecutionEngine *engine, const Value &ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
-struct URIErrorPrototype: URIErrorObject
+struct URIErrorPrototype: ErrorObject
 {
-    URIErrorPrototype(ExecutionEngine *engine): URIErrorObject(engine, Value::undefinedValue()) { vtbl = &static_vtbl; }
+    URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { vtbl = &static_vtbl; }
     void init(ExecutionEngine *engine, const Value &ctor) { ErrorPrototype::init(engine, ctor, this); }
 };
 
index 995434a..5989203 100644 (file)
@@ -80,7 +80,7 @@ FunctionObject::FunctionObject(ExecutionContext *scope, String *name)
     , function(0)
 {
     vtbl = &static_vtbl;
-    prototype = scope->engine->functionPrototype;
+    setPrototype(scope->engine->functionPrototype);
 
     type = Type_FunctionObject;
     needsActivation = true;
@@ -94,6 +94,21 @@ FunctionObject::FunctionObject(ExecutionContext *scope, String *name)
          defineReadonlyProperty(scope->engine->id_name, Value::fromString(name));
 }
 
+FunctionObject::FunctionObject(InternalClass *ic)
+    : Object(ic)
+    , scope(ic->engine->rootContext)
+    , name(name)
+    , formalParameterList(0)
+    , varList(0)
+    , formalParameterCount(0)
+    , varCount(0)
+    , function(0)
+{
+    vtbl = &static_vtbl;
+
+    type = Type_FunctionObject;
+}
+
 FunctionObject::~FunctionObject()
 {
     if (function)
@@ -120,7 +135,7 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value)
         ctx->throwTypeError();
 
     while (v) {
-        v = v->prototype;
+        v = v->prototype();
 
         if (! v)
             break;
@@ -139,7 +154,7 @@ Value FunctionObject::construct(Managed *that, const CallData &)
     Object *obj = v4->newObject();
     Value proto = f->get(v4->id_prototype);
     if (proto.isObject())
-        obj->prototype = proto.objectValue();
+        obj->setPrototype(proto.objectValue());
     return Value::fromObject(obj);
 }
 
@@ -235,8 +250,8 @@ Value FunctionCtor::call(Managed *that, const CallData &d)
     return construct(that, d);
 }
 
-FunctionPrototype::FunctionPrototype(ExecutionContext *ctx)
-    : FunctionObject(ctx)
+FunctionPrototype::FunctionPrototype(InternalClass *ic)
+    : FunctionObject(ic)
 {
 }
 
@@ -375,7 +390,7 @@ Value ScriptFunction::construct(Managed *that, const CallData &d)
     Object *obj = v4->newObject();
     Value proto = f->get(v4->id_prototype);
     if (proto.isObject())
-        obj->prototype = proto.objectValue();
+        obj->setPrototype(proto.objectValue());
 
     ExecutionContext *context = v4->current;
     CallData dd = d;
@@ -469,7 +484,7 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
     Object *obj = v4->newObject();
     Value proto = f->get(v4->id_prototype);
     if (proto.isObject())
-        obj->prototype = proto.objectValue();
+        obj->setPrototype(proto.objectValue());
 
     ExecutionContext *context = v4->current;
     void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
index fdfb1e6..8b900db 100644 (file)
@@ -108,6 +108,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
     Function *function;
 
     FunctionObject(ExecutionContext *scope, String *name = 0);
+    FunctionObject(InternalClass *ic);
     ~FunctionObject();
 
     Value newInstance();
@@ -144,7 +145,7 @@ protected:
 
 struct FunctionPrototype: FunctionObject
 {
-    FunctionPrototype(ExecutionContext *ctx);
+    FunctionPrototype(InternalClass *ic);
     void init(ExecutionContext *ctx, const Value &ctor);
 
     static Value method_toString(SimpleCallContext *ctx);
index 50803db..59b1989 100644 (file)
@@ -50,6 +50,9 @@ QT_BEGIN_NAMESPACE
 
 uint QV4::qHash(const QV4::InternalClassTransition &t, uint)
 {
+    if (t.flags == QV4::InternalClassTransition::ProtoChange)
+        // INT_MAX is prime, so this should give a decent distribution of keys
+        return (uint)((quintptr)t.prototype * INT_MAX);
     return t.id->hashValue ^ t.flags;
 }
 
@@ -160,6 +163,8 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
     // create a new class and add it to the tree
     InternalClass *newClass = engine->newClass(*this);
     newClass->propertyData[idx] = data;
+
+    transitions.insert(t, newClass);
     return newClass;
 
 }
@@ -178,8 +183,17 @@ InternalClass *InternalClass::changePrototype(Object *proto)
         return tit.value();
 
     // create a new class and add it to the tree
-    InternalClass *newClass = engine->newClass(*this);
-    newClass->prototype = proto;
+    InternalClass *newClass;
+    if (this == engine->emptyClass) {
+        newClass = engine->newClass(*this);
+        newClass->prototype = proto;
+    } else {
+        newClass = engine->emptyClass->changePrototype(proto);
+        for (int i = 0; i < nameMap.size(); ++i)
+            newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
+    }
+
+    transitions.insert(t, newClass);
     return newClass;
 }
 
@@ -231,7 +245,7 @@ void InternalClass::removeMember(Object *object, Identifier *id)
     }
 
     // create a new class and add it to the tree
-    object->internalClass = engine->emptyClass;
+    object->internalClass = engine->emptyClass->changePrototype(prototype);
     for (int i = 0; i < nameMap.size(); ++i) {
         if (i == propIdx)
             continue;
@@ -259,6 +273,7 @@ InternalClass *InternalClass::sealed()
         return m_sealed;
 
     m_sealed = engine->emptyClass;
+    m_sealed = m_sealed->changePrototype(prototype);
     for (int i = 0; i < nameMap.size(); ++i) {
         PropertyAttributes attrs = propertyData.at(i);
         attrs.setConfigurable(false);
@@ -275,6 +290,7 @@ InternalClass *InternalClass::frozen()
         return m_frozen;
 
     m_frozen = engine->emptyClass;
+    m_frozen = m_frozen->changePrototype(prototype);
     for (int i = 0; i < nameMap.size(); ++i) {
         PropertyAttributes attrs = propertyData.at(i);
         attrs.setWritable(false);
@@ -315,7 +331,8 @@ void InternalClass::destroy()
 
 void InternalClass::markObjects()
 {
-    prototype->mark();
+    if (prototype)
+        prototype->mark();
     for (QHash<Transition, InternalClass *>::ConstIterator it = transitions.begin(), end = transitions.end();
          it != end; ++it)
         it.value()->markObjects();
index 68a4c5c..740f30f 100644 (file)
@@ -861,7 +861,7 @@ JsonObject::JsonObject(ExecutionContext *context)
     : Object(context->engine)
 {
     type = Type_JSONObject;
-    prototype = context->engine->objectPrototype;
+    setPrototype(context->engine->objectPrototype);
 
     defineDefaultProperty(context, QStringLiteral("parse"), method_parse, 2);
     defineDefaultProperty(context, QStringLiteral("stringify"), method_stringify, 3);
index b7a6f73..94df968 100644 (file)
@@ -49,7 +49,7 @@ Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
 {
     int i = 0;
     while (i < level && obj && obj->internalClass == classList[i]) {
-        obj = obj->prototype;
+        obj = obj->prototype();
         ++i;
     }
 
@@ -68,7 +68,7 @@ Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
             return obj->memberData + index;
         }
 
-        obj = obj->prototype;
+        obj = obj->prototype();
         ++i;
     }
     level = i;
@@ -80,7 +80,7 @@ Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
             return obj->memberData + index;
         }
 
-        obj = obj->prototype;
+        obj = obj->prototype();
     }
     return 0;
 }
@@ -122,9 +122,9 @@ void Lookup::getter1(Lookup *l, Value *result, const Value &object)
 {
     if (Object *o = object.asObject()) {
         if (l->classList[0] == o->internalClass &&
-            l->classList[1] == o->prototype->internalClass) {
+            l->classList[1] == o->prototype()->internalClass) {
             if (result)
-                *result = o->prototype->memberData[l->index].value;
+                *result = o->prototype()->memberData[l->index].value;
             return;
         }
     }
@@ -136,9 +136,9 @@ void Lookup::getter2(Lookup *l, Value *result, const Value &object)
 {
     if (Object *o = object.asObject()) {
         if (l->classList[0] == o->internalClass) {
-            o = o->prototype;
+            o = o->prototype();
             if (l->classList[1] == o->internalClass) {
-                o = o->prototype;
+                o = o->prototype();
                 if (l->classList[2] == o->internalClass) {
                     if (result)
                         *result = o->memberData[l->index].value;
@@ -177,9 +177,9 @@ void Lookup::getterAccessor1(Lookup *l, Value *result, const Value &object)
 {
     if (Object *o = object.asObject()) {
         if (l->classList[0] == o->internalClass &&
-            l->classList[1] == o->prototype->internalClass) {
+            l->classList[1] == o->prototype()->internalClass) {
             Value res;
-            FunctionObject *getter = o->prototype->memberData[l->index].getter();
+            FunctionObject *getter = o->prototype()->memberData[l->index].getter();
             if (!getter) {
                 res = Value::undefinedValue();
             } else {
@@ -200,9 +200,9 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object)
 {
     if (Object *o = object.asObject()) {
         if (l->classList[0] == o->internalClass) {
-            o = o->prototype;
+            o = o->prototype();
             if (l->classList[1] == o->internalClass) {
-                o = o->prototype;
+                o = o->prototype();
                 if (l->classList[2] == o->internalClass) {
                     Value res;
                     FunctionObject *getter = o->memberData[l->index].getter();
@@ -271,8 +271,8 @@ void Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx, Value *result)
 {
     Object *o = ctx->engine->globalObject;
     if (l->classList[0] == o->internalClass &&
-        l->classList[1] == o->prototype->internalClass) {
-        *result = o->prototype->memberData[l->index].value;
+        l->classList[1] == o->prototype()->internalClass) {
+        *result = o->prototype()->memberData[l->index].value;
         return;
     }
     l->globalGetter = globalGetterGeneric;
@@ -283,11 +283,11 @@ void Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx, Value *result)
 {
     Object *o = ctx->engine->globalObject;
     if (l->classList[0] == o->internalClass) {
-        o = o->prototype;
+        o = o->prototype();
         if (l->classList[1] == o->internalClass) {
-            o = o->prototype;
+            o = o->prototype();
             if (l->classList[2] == o->internalClass) {
-                *result = o->prototype->memberData[l->index].value;
+                *result = o->prototype()->memberData[l->index].value;
                 return;
             }
         }
@@ -318,8 +318,8 @@ void Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *resu
 {
     Object *o = ctx->engine->globalObject;
     if (l->classList[0] == o->internalClass &&
-        l->classList[1] == o->prototype->internalClass) {
-        FunctionObject *getter = o->prototype->memberData[l->index].getter();
+        l->classList[1] == o->prototype()->internalClass) {
+        FunctionObject *getter = o->prototype()->memberData[l->index].getter();
         if (!getter) {
             *result = Value::undefinedValue();
         } else {
@@ -337,9 +337,9 @@ void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *resu
 {
     Object *o = ctx->engine->globalObject;
     if (l->classList[0] == o->internalClass) {
-        o = o->prototype;
+        o = o->prototype();
         if (l->classList[1] == o->internalClass) {
-            o = o->prototype;
+            o = o->prototype();
             if (l->classList[2] == o->internalClass) {
                 FunctionObject *getter = o->memberData[l->index].getter();
                 if (!getter) {
@@ -384,7 +384,7 @@ void Lookup::setterInsert0(Lookup *l, const Value &object, const Value &value)
 {
     Object *o = object.asObject();
     if (o && o->internalClass == l->classList[0]) {
-        if (!o->prototype) {
+        if (!o->prototype()) {
             o->memberData[l->index].value = value;
             o->internalClass = l->classList[3];
             return;
@@ -399,7 +399,7 @@ void Lookup::setterInsert1(Lookup *l, const Value &object, const Value &value)
 {
     Object *o = object.asObject();
     if (o && o->internalClass == l->classList[0]) {
-        Object *p = o->prototype;
+        Object *p = o->prototype();
         if (p && p->internalClass == l->classList[1]) {
             o->memberData[l->index].value = value;
             o->internalClass = l->classList[3];
@@ -415,9 +415,9 @@ void Lookup::setterInsert2(Lookup *l, const Value &object, const Value &value)
 {
     Object *o = object.asObject();
     if (o && o->internalClass == l->classList[0]) {
-        Object *p = o->prototype;
+        Object *p = o->prototype();
         if (p && p->internalClass == l->classList[1]) {
-            p = p->prototype;
+            p = p->prototype();
             if (p && p->internalClass == l->classList[2]) {
                 o->ensureMemberIndex(l->index);
                 o->memberData[l->index].value = value;
index 7aa56f5..ac98332 100644 (file)
@@ -54,7 +54,7 @@ MathObject::MathObject(ExecutionContext *ctx)
     : Object(ctx->engine)
 {
     type = Type_MathObject;
-    prototype = ctx->engine->objectPrototype;
+    setPrototype(ctx->engine->objectPrototype);
 
     defineReadonlyProperty(ctx->engine, QStringLiteral("E"), Value::fromDouble(::exp(1.0)));
     defineReadonlyProperty(ctx->engine, QStringLiteral("LN2"), Value::fromDouble(::log(2.0)));
index 224840e..096b4b3 100644 (file)
@@ -62,7 +62,7 @@ protected:
 
 struct NumberPrototype: NumberObject
 {
-    NumberPrototype(ExecutionEngine *engine): NumberObject(engine, Value::fromDouble(0)) {}
+    NumberPrototype(InternalClass *ic): NumberObject(ic) {}
     void init(ExecutionContext *ctx, const Value &ctor);
 
     static Value method_toString(SimpleCallContext *ctx);
index f76abdb..fd4c031 100644 (file)
@@ -70,7 +70,6 @@ DEFINE_MANAGED_VTABLE(Object);
 
 Object::Object(ExecutionEngine *engine)
     : Managed(engine->emptyClass)
-    , prototype(0)
     , memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
     , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
 {
@@ -81,7 +80,6 @@ Object::Object(ExecutionEngine *engine)
 
 Object::Object(InternalClass *internalClass)
     : Managed(internalClass)
-    , prototype(0)
     , memberDataAlloc(InlinePropertySize), memberData(inlineProperties)
     , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), arrayAttributes(0), arrayData(0), sparseArray(0)
 {
@@ -106,6 +104,18 @@ Object::~Object()
     _data = 0;
 }
 
+bool Object::setPrototype(Object *proto)
+{
+    Object *pp = proto;
+    while (pp) {
+        if (pp == this)
+            return false;
+        pp = pp->prototype();
+    }
+    internalClass = internalClass->changePrototype(proto);
+    return true;
+}
+
 void Object::destroy(Managed *that)
 {
     static_cast<Object *>(that)->~Object();
@@ -267,8 +277,6 @@ void Object::defineReadonlyProperty(String *name, Value value)
 void Object::markObjects(Managed *that)
 {
     Object *o = static_cast<Object *>(that);
-    if (o->prototype)
-        o->prototype->mark();
 
     for (int i = 0; i < o->internalClass->size; ++i) {
         const Property &pd = o->memberData[i];
@@ -373,7 +381,7 @@ Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *at
             return o->memberData + idx;
         }
 
-        o = o->prototype;
+        o = o->prototype();
     }
     if (attrs)
         *attrs = Attr_Invalid;
@@ -401,7 +409,7 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
                 return p;
             }
         }
-        o = o->prototype;
+        o = o->prototype();
     }
     if (attrs)
         *attrs = Attr_Invalid;
@@ -417,7 +425,7 @@ bool Object::__hasProperty__(String *name) const
     while (o) {
         if (!o->query(name).isEmpty())
             return true;
-        o = o->prototype;
+        o = o->prototype();
     }
 
     return false;
@@ -432,7 +440,7 @@ bool Object::__hasProperty__(uint index) const
     while (o) {
         if (!o->queryIndexed(index).isEmpty())
             return true;
-        o = o->prototype;
+        o = o->prototype();
     }
 
     return false;
@@ -565,19 +573,19 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
     l->classList[0] = c;
     l->classList[3] = o->internalClass;
     l->index = idx;
-    if (!o->prototype) {
+    if (!o->prototype()) {
         l->setter = Lookup::setterInsert0;
         return;
     }
-    o = o->prototype;
+    o = o->prototype();
     l->classList[1] = o->internalClass;
-    if (!o->prototype) {
+    if (!o->prototype()) {
         l->setter = Lookup::setterInsert1;
         return;
     }
-    o = o->prototype;
+    o = o->prototype();
     l->classList[2] = o->internalClass;
-    if (!o->prototype)
+    if (!o->prototype())
         l->setter = Lookup::setterInsert2;
 }
 
@@ -660,7 +668,7 @@ Value Object::internalGet(String *name, bool *hasProperty)
             return getValue(o->memberData + idx, o->internalClass->propertyData.at(idx));
         }
 
-        o = o->prototype;
+        o = o->prototype();
     }
 
     if (hasProperty)
@@ -690,7 +698,7 @@ Value Object::internalGetIndexed(uint index, bool *hasProperty)
                 break;
             }
         }
-        o = o->prototype;
+        o = o->prototype();
     }
 
     if (pd) {
@@ -742,12 +750,12 @@ void Object::internalPut(String *name, const Value &value)
             pd->value = value;
         }
         return;
-    } else if (!prototype) {
+    } else if (!prototype()) {
         if (!extensible)
             goto reject;
     } else {
         // clause 4
-        if ((pd = prototype->__getPropertyDescriptor__(name, &attrs))) {
+        if ((pd = prototype()->__getPropertyDescriptor__(name, &attrs))) {
             if (attrs.isAccessor()) {
                 if (!pd->setter())
                     goto reject;
@@ -820,12 +828,12 @@ void Object::internalPutIndexed(uint index, const Value &value)
         else
             pd->value = value;
         return;
-    } else if (!prototype) {
+    } else if (!prototype()) {
         if (!extensible)
             goto reject;
     } else {
         // clause 4
-        if ((pd = prototype->__getPropertyDescriptor__(index, &attrs))) {
+        if ((pd = prototype()->__getPropertyDescriptor__(index, &attrs))) {
             if (attrs.isAccessor()) {
                 if (!pd->setter())
                     goto reject;
index fc9af6f..7d4aae5 100644 (file)
@@ -105,7 +105,6 @@ typedef Value (*PropertyEnumeratorFunction)(Object *object);
 typedef PropertyAttributes (*PropertyQueryFunction)(const Object *object, String *name);
 
 struct Q_QML_EXPORT Object: Managed {
-    Object *prototype;
     uint memberDataAlloc;
     Property *memberData;
 
@@ -128,6 +127,9 @@ struct Q_QML_EXPORT Object: Managed {
     Object(InternalClass *internalClass);
     ~Object();
 
+    Object *prototype() const { return internalClass->prototype; }
+    bool setPrototype(Object *proto);
+
     Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
     Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0);
 
@@ -277,7 +279,7 @@ public:
     inline bool protoHasArray() {
         Object *p = this;
 
-        while ((p = p->prototype))
+        while ((p = p->prototype()))
             if (p->arrayDataLen)
                 return true;
 
@@ -350,11 +352,13 @@ protected:
 
 struct BooleanObject: Object {
     Value value;
+    BooleanObject(InternalClass *ic): Object(ic), value(Value::fromBoolean(false)) { type = Type_BooleanObject; }
     BooleanObject(ExecutionEngine *engine, const Value &value): Object(engine), value(value) { type = Type_BooleanObject; }
 };
 
 struct NumberObject: Object {
     Value value;
+    NumberObject(InternalClass *ic): Object(ic), value(Value::fromInt32(0)) { type = Type_NumberObject; }
     NumberObject(ExecutionEngine *engine, const Value &value): Object(engine), value(value) { type = Type_NumberObject; }
 };
 
@@ -363,6 +367,7 @@ struct ArrayObject: Object {
         LengthPropertyIndex = 0
     };
 
+    ArrayObject(InternalClass *ic) : Object(ic) { init(ic->engine); }
     ArrayObject(ExecutionEngine *engine) : Object(engine) { init(engine); }
     ArrayObject(ExecutionEngine *engine, const QStringList &list);
     void init(ExecutionEngine *engine);
index a89bfdb..338398c 100644 (file)
@@ -82,7 +82,7 @@ Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *a
         }
 
         if (flags & WithProtoChain)
-            current = current->prototype;
+            current = current->prototype();
         else
             current = 0;
 
index ec60a9b..fbf8664 100644 (file)
@@ -86,7 +86,7 @@ Value ObjectCtor::construct(Managed *that, const CallData &d)
         Object *obj = v4->newObject();
         Value proto = ctor->get(v4->id_prototype);
         if (proto.isObject())
-            obj->prototype = proto.objectValue();
+            obj->setPrototype(proto.objectValue());
         return Value::fromObject(obj);
     }
     return __qmljs_to_object(v4->current, d.args[0]);
@@ -139,7 +139,7 @@ Value ObjectPrototype::method_getPrototypeOf(SimpleCallContext *ctx)
     if (! o.isObject())
         ctx->throwTypeError();
 
-    Object *p = o.objectValue()->prototype;
+    Object *p = o.objectValue()->prototype();
     return p ? Value::fromObject(p) : Value::nullValue();
 }
 
@@ -172,7 +172,7 @@ Value ObjectPrototype::method_create(SimpleCallContext *ctx)
         ctx->throwTypeError();
 
     Object *newObject = ctx->engine->newObject();
-    newObject->prototype = O.asObject();
+    newObject->setPrototype(O.asObject());
 
     Value objValue = Value::fromObject(newObject);
     if (ctx->argumentCount > 1 && !ctx->argument(1).isUndefined()) {
@@ -412,11 +412,11 @@ Value ObjectPrototype::method_isPrototypeOf(SimpleCallContext *ctx)
         return Value::fromBoolean(false);
 
     Object *O = ctx->thisObject.toObject(ctx);
-    Object *proto = V.objectValue()->prototype;
+    Object *proto = V.objectValue()->prototype();
     while (proto) {
         if (O == proto)
             return Value::fromBoolean(true);
-        proto = proto->prototype;
+        proto = proto->prototype();
     }
     return Value::fromBoolean(false);
 }
@@ -481,7 +481,7 @@ Value ObjectPrototype::method_get_proto(SimpleCallContext *ctx)
     if (!o)
         ctx->throwTypeError();
 
-    return Value::fromObject(o->prototype);
+    return Value::fromObject(o->prototype());
 }
 
 Value ObjectPrototype::method_set_proto(SimpleCallContext *ctx)
@@ -493,22 +493,13 @@ Value ObjectPrototype::method_set_proto(SimpleCallContext *ctx)
     Value proto = ctx->argument(0);
     bool ok = false;
     if (proto.isNull()) {
-        o->prototype = 0;
+        o->setPrototype(0);
         ok = true;
     } else if (Object *p = proto.asObject()) {
-        if (o->prototype == p) {
+        if (o->prototype() == p) {
             ok = true;
         } else if (o->extensible) {
-            Object *pp = p;
-            while (pp) {
-                if (pp == o)
-                    break;
-                pp = pp->prototype;
-            }
-            if (!pp) {
-                ok = true;
-                o->prototype = p;
-            }
+            ok = o->setPrototype(p);
         }
     }
     if (!ok)
index afa0ce0..be51c41 100644 (file)
@@ -62,7 +62,7 @@ protected:
 
 struct ObjectPrototype: Object
 {
-    ObjectPrototype(ExecutionEngine *engine) : Object(engine) {}
+    ObjectPrototype(InternalClass *ic) : Object(ic) {}
 
     void init(ExecutionContext *ctx, const Value &ctor);
 
index 7041348..fe82192 100644 (file)
@@ -246,7 +246,7 @@ QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
     , m_object(object)
 {
     vtbl = &static_vtbl;
-    prototype = engine->objectPrototype;
+    setPrototype(engine->objectPrototype);
 
     m_destroy = engine->newIdentifier(QStringLiteral("destroy"));
     m_toString = engine->newIdentifier(QStringLiteral("toString"));
@@ -1759,7 +1759,7 @@ QmlSignalHandler::QmlSignalHandler(ExecutionEngine *engine, QObject *object, int
     , m_signalIndex(signalIndex)
 {
     vtbl = &static_vtbl;
-    prototype = engine->objectPrototype;
+    setPrototype(engine->objectPrototype);
 }
 
 DEFINE_MANAGED_VTABLE(QmlSignalHandler);
index 16b23e2..05829b4 100644 (file)
@@ -70,6 +70,14 @@ using namespace QV4;
 
 DEFINE_MANAGED_VTABLE(RegExpObject);
 
+RegExpObject::RegExpObject(InternalClass *ic)
+    : Object(ic)
+    , value(RegExp::create(ic->engine, QString(), false, false))
+    , global(false)
+{
+    init(ic->engine);
+}
+
 RegExpObject::RegExpObject(ExecutionEngine *engine, RegExp* value, bool global)
     : Object(engine)
     , value(value)
index 2179dbd..6c4f12c 100644 (file)
@@ -77,6 +77,8 @@ struct RegExpObject: Object {
     RegExp* value;
     Property *lastIndexProperty(ExecutionContext *ctx);
     bool global;
+
+    RegExpObject(InternalClass *ic);
     RegExpObject(ExecutionEngine *engine, RegExp* value, bool global);
     RegExpObject(ExecutionEngine *engine, const QRegExp &re);
     ~RegExpObject() {}
@@ -107,7 +109,7 @@ protected:
 
 struct RegExpPrototype: RegExpObject
 {
-    RegExpPrototype(ExecutionEngine* engine): RegExpObject(engine, RegExp::create(engine, QString()), false) {}
+    RegExpPrototype(InternalClass *ic): RegExpObject(ic) {}
     void init(ExecutionContext *ctx, const Value &ctor);
 
     static Value method_exec(SimpleCallContext *ctx);
index f145050..a9095ff 100644 (file)
@@ -1242,7 +1242,7 @@ void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, Value *result
     assert(ctx->type >= ExecutionContext::Type_CallContext);
     CallContext *c = static_cast<CallContext *>(ctx);
     ArgumentsObject *args = new (c->engine->memoryManager) ArgumentsObject(c);
-    args->prototype = c->engine->objectPrototype;
+    args->setPrototype(c->engine->objectPrototype);
     *result = Value::fromObject(args);
 }
 
index 1d5c271..cc5e2d6 100644 (file)
@@ -172,7 +172,7 @@ public:
     {
         type = Type_QmlSequence;
         vtbl = &static_vtbl;
-        prototype = engine->sequencePrototype;
+        setPrototype(engine->sequencePrototype);
         init(engine);
     }
 
@@ -184,7 +184,7 @@ public:
     {
         type = Type_QmlSequence;
         vtbl = &static_vtbl;
-        prototype = engine->sequencePrototype;
+        setPrototype(engine->sequencePrototype);
         loadReference();
         init(engine);
     }
@@ -523,10 +523,9 @@ template<>
 DEFINE_MANAGED_VTABLE(QQmlRealList);
 
 #define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>(#SequenceType);
-SequencePrototype::SequencePrototype(ExecutionEngine *engine)
-    : QV4::Object(engine)
+SequencePrototype::SequencePrototype(InternalClass *ic)
+    : QV4::Object(ic)
 {
-    prototype = engine->arrayPrototype;
     FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
 }
 #undef REGISTER_QML_SEQUENCE_METATYPE
index 2cade45..ceae4e6 100644 (file)
@@ -65,7 +65,7 @@ namespace QV4 {
 
 struct SequencePrototype : public QV4::Object
 {
-    SequencePrototype(QV4::ExecutionEngine *engine);
+    SequencePrototype(QV4::InternalClass *ic);
 
     void init(QV4::ExecutionEngine *engine);
 
index ab802ca..6fd312a 100644 (file)
@@ -76,6 +76,17 @@ using namespace QV4;
 
 DEFINE_MANAGED_VTABLE(StringObject);
 
+StringObject::StringObject(InternalClass *ic)
+    : Object(ic), value(Value::fromString(ic->engine, ""))
+{
+    vtbl = &static_vtbl;
+    type = Type_StringObject;
+
+    tmpProperty.value = Value::undefinedValue();
+
+    defineReadonlyProperty(ic->engine->id_length, Value::fromInt32(0));
+}
+
 StringObject::StringObject(ExecutionEngine *engine, const Value &value)
     : Object(engine), value(value)
 {
index cf489eb..6d2ccce 100644 (file)
@@ -54,6 +54,7 @@ struct StringObject: Object {
 
     Value value;
     mutable Property tmpProperty;
+    StringObject(InternalClass *ic);
     StringObject(ExecutionEngine *engine, const Value &value);
 
     Property *getIndex(uint index) const;
@@ -78,7 +79,7 @@ protected:
 
 struct StringPrototype: StringObject
 {
-    StringPrototype(ExecutionEngine *engine): StringObject(engine, Value::fromString(engine, QString())) {}
+    StringPrototype(InternalClass *ic): StringObject(ic) {}
     void init(ExecutionEngine *engine, const Value &ctor);
 
     static Value method_toString(SimpleCallContext *context);
index f18c5b5..1989e3d 100644 (file)
@@ -51,13 +51,21 @@ using namespace QV4;
 
 DEFINE_MANAGED_VTABLE(VariantObject);
 
+VariantObject::VariantObject(InternalClass *ic)
+    : Object(ic)
+    , ExecutionEngine::ScarceResourceData(QVariant())
+    , m_vmePropertyReferenceCount(0)
+{
+    vtbl = &static_vtbl;
+}
+
 VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
     : Object(engine)
     , ExecutionEngine::ScarceResourceData(value)
     , m_vmePropertyReferenceCount(0)
 {
     vtbl = &static_vtbl;
-    prototype = engine->variantPrototype;
+    setPrototype(engine->variantPrototype);
     if (isScarce())
         internalClass->engine->scarceResources.insert(this);
 }
@@ -132,10 +140,9 @@ void VariantObject::removeVmePropertyReference()
 }
 
 
-VariantPrototype::VariantPrototype(ExecutionEngine *engine)
-    : VariantObject(engine, QVariant())
+VariantPrototype::VariantPrototype(InternalClass *ic)
+    : VariantObject(ic)
 {
-    prototype = engine->objectPrototype;
 }
 
 void VariantPrototype::init(ExecutionEngine *engine)
index 876539a..eadf0ac 100644 (file)
@@ -68,6 +68,7 @@ struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
 {
     Q_MANAGED
 public:
+    VariantObject(InternalClass *ic);
     VariantObject(ExecutionEngine *engine, const QVariant &value);
 
     static QVariant toVariant(const QV4::Value &v);
@@ -84,7 +85,7 @@ public:
 struct VariantPrototype : VariantObject
 {
 public:
-    VariantPrototype(ExecutionEngine *engine);
+    VariantPrototype(InternalClass *ic);
 
     void init(ExecutionEngine *engine);
 
index 5c26f68..5f3a2e9 100644 (file)
@@ -1342,7 +1342,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
 
     QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine());
     QmlIncubatorObject *r = new (v4->memoryManager) QmlIncubatorObject(args->engine(), mode);
-    r->prototype = e->incubationProto.value().asObject();
+    r->setPrototype(e->incubationProto.value().asObject());
 
     if (!valuemap.isEmpty()) {
         r->valuemap = valuemap;
index 9ba3a51..7c99bbc 100644 (file)
@@ -78,7 +78,7 @@ QV4::Value QmlContextWrapper::qmlScope(QV8Engine *v8, QQmlContextData *ctxt, QOb
     ExecutionEngine *v4 = QV8Engine::getV4(v8);
 
     QmlContextWrapper *w = new (v4->memoryManager) QmlContextWrapper(v8, ctxt, scope);
-    w->prototype = v4->objectPrototype;
+    w->setPrototype(v4->objectPrototype);
     return Value::fromObject(w);
 }
 
@@ -93,7 +93,7 @@ QV4::Value QmlContextWrapper::urlScope(QV8Engine *v8, const QUrl &url)
 
     QmlContextWrapper *w = new (v4->memoryManager) QmlContextWrapper(v8, context, 0);
     w->isNullWrapper = true;
-    w->prototype = v4->objectPrototype;
+    w->setPrototype(v4->objectPrototype);
     return Value::fromObject(w);
 }
 
index 7afbe3f..8b135f2 100644 (file)
@@ -57,7 +57,7 @@ QmlListWrapper::QmlListWrapper(QV8Engine *engine)
       v8(engine)
 {
     vtbl = &static_vtbl;
-    prototype = QV8Engine::getV4(engine)->objectPrototype;
+    setPrototype(QV8Engine::getV4(engine)->objectPrototype);
 }
 
 QmlListWrapper::~QmlListWrapper()
index 4694e33..f248b8b 100644 (file)
@@ -814,7 +814,7 @@ QV4::Value QQmlLocale::locale(QV8Engine *v8engine, const QString &locale)
     QQmlLocaleData *wrapper = new (engine->memoryManager) QQmlLocaleData(engine);
     if (!locale.isEmpty())
         wrapper->locale = QLocale(locale);
-    wrapper->prototype = d->prototype.value().asObject();
+    wrapper->setPrototype(d->prototype.value().asObject());
     return QV4::Value::fromObject(wrapper);
 }
 
index 20c403c..ab64fe1 100644 (file)
@@ -93,7 +93,7 @@ Value QmlTypeWrapper::create(QV8Engine *v8, QObject *o, QQmlType *t, TypeNameMod
     ExecutionEngine *v4 = QV8Engine::getV4(v8);
 
     QmlTypeWrapper *w = new (v4->memoryManager) QmlTypeWrapper(v8);
-    w->prototype = v4->objectPrototype;
+    w->setPrototype(v4->objectPrototype);
     w->mode = mode; w->object = o; w->type = t;
     return Value::fromObject(w);
 }
@@ -107,7 +107,7 @@ Value QmlTypeWrapper::create(QV8Engine *v8, QObject *o, QQmlTypeNameCache *t, co
     ExecutionEngine *v4 = QV8Engine::getV4(v8);
 
     QmlTypeWrapper *w = new (v4->memoryManager) QmlTypeWrapper(v8);
-    w->prototype = v4->objectPrototype;
+    w->setPrototype(v4->objectPrototype);
     w->mode = mode; w->object = o; w->typeNamespace = t; w->importNamespace = importNamespace;
     t->addref();
     return Value::fromObject(w);
index 64baf8b..f494fba 100644 (file)
@@ -145,7 +145,7 @@ Value QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int property,
     initProto(v4);
 
     QmlValueTypeReference *r = new (v4->memoryManager) QmlValueTypeReference(v8);
-    r->prototype = v4->qmlExtensions()->valueTypeWrapperPrototype;
+    r->setPrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
     r->type = type; r->object = object; r->property = property;
     return Value::fromObject(r);
 }
@@ -156,7 +156,7 @@ Value QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, QQmlValu
     initProto(v4);
 
     QmlValueTypeCopy *r = new (v4->memoryManager) QmlValueTypeCopy(v8);
-    r->prototype = v4->qmlExtensions()->valueTypeWrapperPrototype;
+    r->setPrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
     r->type = type; r->value = value;
     return Value::fromObject(r);
 }
index 5045d70..2f93ad5 100644 (file)
@@ -579,7 +579,7 @@ Value Node::create(QV8Engine *engine, NodeImpl *data)
 
     switch (data->type) {
     case NodeImpl::Attr:
-        instance->prototype = Attr::prototype(v4).asObject();
+        instance->setPrototype(Attr::prototype(v4).asObject());
         break;
     case NodeImpl::Comment:
     case NodeImpl::Document:
@@ -591,13 +591,13 @@ Value Node::create(QV8Engine *engine, NodeImpl *data)
     case NodeImpl::ProcessingInstruction:
         return Value::undefinedValue();
     case NodeImpl::CDATA:
-        instance->prototype = CDATA::prototype(v4).asObject();
+        instance->setPrototype(CDATA::prototype(v4).asObject());
         break;
     case NodeImpl::Text:
-        instance->prototype = Text::prototype(v4).asObject();
+        instance->setPrototype(Text::prototype(v4).asObject());
         break;
     case NodeImpl::Element:
-        instance->prototype = Element::prototype(v4).asObject();
+        instance->setPrototype(Element::prototype(v4).asObject());
         break;
     }
 
@@ -609,7 +609,7 @@ Value Element::prototype(ExecutionEngine *engine)
     QQmlXMLHttpRequestData *d = xhrdata(engine->v8Engine);
     if (d->elementPrototype.isEmpty()) {
         Object *p = engine->newObject();
-        p->prototype = NodePrototype::getProto(engine).asObject();
+        p->setPrototype(NodePrototype::getProto(engine).asObject());
         p->defineAccessorProperty(engine, QStringLiteral("tagName"), NodePrototype::method_get_nodeName, 0);
         d->elementPrototype = Value::fromObject(p);
         engine->v8Engine->freezeObject(d->elementPrototype.value());
@@ -622,7 +622,7 @@ Value Attr::prototype(ExecutionEngine *engine)
     QQmlXMLHttpRequestData *d = xhrdata(engine->v8Engine);
     if (d->attrPrototype.isEmpty()) {
         Object *p = engine->newObject();
-        p->prototype = NodePrototype::getProto(engine).asObject();
+        p->setPrototype(NodePrototype::getProto(engine).asObject());
         p->defineAccessorProperty(engine, QStringLiteral("name"), name, 0);
         p->defineAccessorProperty(engine, QStringLiteral("value"), value, 0);
         p->defineAccessorProperty(engine, QStringLiteral("ownerElement"), ownerElement, 0);
@@ -673,7 +673,7 @@ Value CharacterData::prototype(ExecutionEngine *v4)
     QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
     if (d->characterDataPrototype.isEmpty()) {
         Object *p = v4->newObject();
-        p->prototype = NodePrototype::getProto(v4).asObject();
+        p->setPrototype(NodePrototype::getProto(v4).asObject());
         p->defineAccessorProperty(v4, QStringLiteral("data"), NodePrototype::method_get_nodeValue, 0);
         p->defineAccessorProperty(v4, QStringLiteral("length"), length, 0);
         d->characterDataPrototype = Value::fromObject(p);
@@ -704,7 +704,7 @@ Value Text::prototype(ExecutionEngine *v4)
     QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
     if (d->textPrototype.isEmpty()) {
         Object *p = v4->newObject();
-        p->prototype = CharacterData::prototype(v4).asObject();
+        p->setPrototype(CharacterData::prototype(v4).asObject());
         p->defineAccessorProperty(v4, QStringLiteral("isElementContentWhitespace"), isElementContentWhitespace, 0);
         p->defineAccessorProperty(v4, QStringLiteral("wholeText"), wholeText, 0);
         d->textPrototype = Value::fromObject(p);
@@ -719,7 +719,7 @@ Value CDATA::prototype(ExecutionEngine *v4)
     QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
     if (d->cdataPrototype.isEmpty()) {
         Object *p = v4->newObject();
-        p->prototype = Text::prototype(v4).asObject();
+        p->setPrototype(Text::prototype(v4).asObject());
         d->cdataPrototype = Value::fromObject(p);
         v4->v8Engine->freezeObject(d->cdataPrototype);
     }
@@ -731,7 +731,7 @@ Value Document::prototype(ExecutionEngine *v4)
     QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
     if (d->documentPrototype.isEmpty()) {
         Object *p = v4->newObject();
-        p->prototype = NodePrototype::getProto(v4).asObject();
+        p->setPrototype(NodePrototype::getProto(v4).asObject());
         p->defineAccessorProperty(v4, QStringLiteral("xmlVersion"), xmlVersion, 0);
         p->defineAccessorProperty(v4, QStringLiteral("xmlEncoding"), xmlEncoding, 0);
         p->defineAccessorProperty(v4, QStringLiteral("xmlStandalone"), xmlStandalone, 0);
@@ -826,7 +826,7 @@ Value Document::load(QV8Engine *engine, const QByteArray &data)
     }
 
     Object *instance = new (v4->memoryManager) Node(v4, document);
-    instance->prototype = Document::prototype(v4).asObject();
+    instance->setPrototype(Document::prototype(v4).asObject());
     return Value::fromObject(instance);
 }
 
@@ -893,7 +893,7 @@ Value NamedNodeMap::create(QV8Engine *engine, NodeImpl *data, const QList<NodeIm
     ExecutionEngine *v4 = QV8Engine::getV4(engine);
 
     NamedNodeMap *instance = new (v4->memoryManager) NamedNodeMap(v4, data, list);
-    instance->prototype = v4->objectPrototype;
+    instance->setPrototype(v4->objectPrototype);
     return Value::fromObject(instance);
 }
 
@@ -935,7 +935,7 @@ Value NodeList::create(QV8Engine *engine, NodeImpl *data)
     QQmlXMLHttpRequestData *d = xhrdata(engine);
     ExecutionEngine *v4 = QV8Engine::getV4(engine);
     NodeList *instance = new (v4->memoryManager) NodeList(v4, data);
-    instance->prototype = v4->objectPrototype;
+    instance->setPrototype(v4->objectPrototype);
     return Value::fromObject(instance);
 }
 
@@ -1574,7 +1574,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
         QV8Engine *engine = that->engine()->v8Engine;
         QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(engine, engine->networkAccessManager());
         QQmlXMLHttpRequestWrapper *w = new (that->engine()->memoryManager) QQmlXMLHttpRequestWrapper(that->engine(), r);
-        w->prototype = ctor->proto;
+        w->setPrototype(ctor->proto);
         return Value::fromObject(w);
     }
 
index ac1cdef..3f67de2 100644 (file)
@@ -1309,7 +1309,7 @@ Value QtObject::method_get_inputMethod(SimpleCallContext *ctx)
 QV4::ConsoleObject::ConsoleObject(ExecutionEngine *v4)
     : Object(v4)
 {
-    prototype = v4->objectPrototype;
+    setPrototype(v4->objectPrototype);
 
     defineDefaultProperty(v4, QStringLiteral("debug"), method_log);
     defineDefaultProperty(v4, QStringLiteral("log"), method_log);
index 96c92c4..117fea2 100644 (file)
@@ -825,7 +825,7 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
             return true;
         } else if (QV4::Object *o = value.asObject()) {
             // Look in the prototype chain.
-            QV4::Object *proto = o->prototype;
+            QV4::Object *proto = o->prototype();
             while (proto) {
                 bool canCast = false;
                 if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
@@ -845,7 +845,7 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
                         *reinterpret_cast<void* *>(data) = var.data();
                     return true;
                 }
-                proto = proto->prototype;
+                proto = proto->prototype();
             }
         }
     } else if (value.isNull() && name.endsWith('*')) {
index 91b20e6..b1b4862 100644 (file)
@@ -2379,7 +2379,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
     QV8Engine *v8 = model->m_cacheMetaType->v8Engine;
     QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
     QV4::Object *o = new (v4->memoryManager) QQmlDelegateModelItemObject(v4, cacheItem);
-    o->prototype = model->m_cacheMetaType->modelItemProto.value().asObject();
+    o->setPrototype(model->m_cacheMetaType->modelItemProto.value().asObject());
     ++cacheItem->scriptRef;
 
     return QQmlV4Handle(QV4::Value::fromObject(o));
@@ -3160,7 +3160,7 @@ public:
 
         QV4::Object *changeProto = engineData(v4->v8Engine)->changeProto.value().asObject();
         QQmlDelegateModelGroupChange *object = new (v4->memoryManager) QQmlDelegateModelGroupChange(v4);
-        object->prototype = changeProto;
+        object->setPrototype(changeProto);
         object->change = change;
 
         if (hasProperty)
index 4e81275..ffd9de0 100644 (file)
@@ -429,7 +429,7 @@ public:
         }
         QV4::Object *proto = type->prototype.value().asObject();
         QV4::Object *o = new (proto->engine()->memoryManager) QQmlDelegateModelItemObject(proto->engine(), this);
-        o->prototype = proto;
+        o->setPrototype(proto);
         QV4::Value data = QV4::Value::fromObject(o);
         ++scriptRef;
         return data;
@@ -602,7 +602,7 @@ public:
     {
         QQmlAdaptorModelEngineData *data = engineData(v4->v8Engine);
         QV4::Object *o = new (v4->memoryManager) QQmlDelegateModelItemObject(v4, this);
-        o->prototype = data->listItemProto.value().asObject();
+        o->setPrototype(data->listItemProto.value().asObject());
         QV4::Value val = QV4::Value::fromObject(o);
         ++scriptRef;
         return val;
index d2014de..7a95a1c 100644 (file)
@@ -544,7 +544,7 @@ public:
     QQuickJSContext2DPrototype(QV4::ExecutionEngine *engine)
         : QV4::Object(engine)
     {
-        prototype = engine->objectPrototype;
+        setPrototype(engine->objectPrototype);
         defineDefaultProperty(engine, QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
         defineDefaultProperty(engine, QStringLiteral("restore"), method_restore, 0);
         defineDefaultProperty(engine, QStringLiteral("moveTo"), method_moveTo, 0);
@@ -916,7 +916,7 @@ static QV4::Value qt_create_image_data(qreal w, qreal h, QV8Engine* engine, cons
     QQuickContext2DEngineData *ed = engineData(engine);
     QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
     QQuickJSContext2DPixelData *pixelData = new (v4->memoryManager) QQuickJSContext2DPixelData(v4);
-    pixelData->prototype = ed->pixelArrayProto.value().asObject();
+    pixelData->setPrototype(ed->pixelArrayProto.value().asObject());
 
     if (image.isNull()) {
         pixelData->image = QImage(w, h, QImage::Format_ARGB32);
@@ -1518,7 +1518,7 @@ QV4::Value QQuickJSContext2DPrototype::method_createLinearGradient(QV4::SimpleCa
         QQuickContext2DEngineData *ed = engineData(engine);
 
         QQuickContext2DStyle *gradient = new (v4->memoryManager) QQuickContext2DStyle(v4);
-        gradient->prototype = ed->gradientProto.value().asObject();
+        gradient->setPrototype(ed->gradientProto.value().asObject());
         gradient->brush = QLinearGradient(x0, y0, x1, y1);
         return QV4::Value::fromObject(gradient);
     }
@@ -1571,7 +1571,7 @@ QV4::Value QQuickJSContext2DPrototype::method_createRadialGradient(QV4::SimpleCa
         QQuickContext2DEngineData *ed = engineData(engine);
 
         QQuickContext2DStyle *gradient = new (v4->memoryManager) QQuickContext2DStyle(v4);
-        gradient->prototype = ed->gradientProto.value().asObject();
+        gradient->setPrototype(ed->gradientProto.value().asObject());
         gradient->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
         return QV4::Value::fromObject(gradient);
     }
@@ -1616,7 +1616,7 @@ QV4::Value QQuickJSContext2DPrototype::method_createConicalGradient(QV4::SimpleC
         QQuickContext2DEngineData *ed = engineData(engine);
 
         QQuickContext2DStyle *gradient = new (v4->memoryManager) QQuickContext2DStyle(v4);
-        gradient->prototype = ed->gradientProto.value().asObject();
+        gradient->setPrototype(ed->gradientProto.value().asObject());
         gradient->brush = QConicalGradient(x, y, angle);
         return QV4::Value::fromObject(gradient);
     }
@@ -4134,7 +4134,7 @@ void QQuickContext2D::setV8Engine(QV8Engine *engine)
         QQuickContext2DEngineData *ed = engineData(engine);
         QV4::ExecutionEngine *v4Engine = QV8Engine::getV4(engine);
         QQuickJSContext2D *wrapper = new (v4Engine->memoryManager) QQuickJSContext2D(v4Engine);
-        wrapper->prototype = ed->contextPrototype.value().asObject();
+        wrapper->setPrototype(ed->contextPrototype.value().asObject());
         wrapper->context = this;
         m_v4value = QV4::Value::fromObject(wrapper);
     }
index 5bf5dbb..e1c228d 100644 (file)
@@ -6,7 +6,6 @@
 10.4.3-1-104 failing
 10.4.3-1-106 failing
 11.2.3-3_3 failing
-S11.8.6_A5_T2 failing
 S13_A15_T4 failing
 S13.2.3_A1 failing
 S15.4.4.3_A1_T1 failing
@@ -20,4 +19,3 @@ Sbp_12.5_A9_T3 failing
 Sbp_12.6.1_A13_T3 failing
 Sbp_12.6.2_A13_T3 failing
 Sbp_12.6.4_A13_T3 failing
-
index 845f781..1e78ac3 100644 (file)
@@ -190,10 +190,10 @@ int main(int argc, char *argv[])
 
         QV4::Object *globalObject = vm.globalObject;
         QV4::Object *print = new (ctx->engine->memoryManager) builtins::Print(ctx);
-        print->prototype = ctx->engine->objectPrototype;
+        print->setPrototype(ctx->engine->objectPrototype);
         globalObject->put(vm.newIdentifier(QStringLiteral("print")), QV4::Value::fromObject(print));
         QV4::Object *gc = new (ctx->engine->memoryManager) builtins::GC(ctx);
-        gc->prototype = ctx->engine->objectPrototype;
+        gc->setPrototype(ctx->engine->objectPrototype);
         globalObject->put(vm.newIdentifier(QStringLiteral("gc")), QV4::Value::fromObject(gc));
 
         foreach (const QString &fn, args) {