Convert FunctionObject derived classes to new construction scheme
authorLars Knoll <lars.knoll@digia.com>
Fri, 9 May 2014 09:35:47 +0000 (11:35 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 22 Jul 2014 11:49:17 +0000 (13:49 +0200)
Change-Id: I0d43a79ed531a9d651bd00866d73113c05d95a09
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4value_p.h
src/qml/types/qquickworkerscript.cpp

index 84c522e..1f7d756 100644 (file)
@@ -336,7 +336,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     numberCtor = new (memoryManager) NumberCtor(rootContext);
     booleanCtor = new (memoryManager) BooleanCtor(rootContext);
     arrayCtor = new (memoryManager) ArrayCtor(rootContext);
-    functionCtor = new (memoryManager) FunctionCtor(rootContext);
+    functionCtor = static_cast<HeapObject *>(new (this) FunctionCtor::Data(rootContext));
     dateCtor = new (memoryManager) DateCtor(rootContext);
     regExpCtor = new (memoryManager) RegExpCtor(rootContext);
     errorCtor = new (memoryManager) ErrorCtor(rootContext);
@@ -412,7 +412,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
 
     Scoped<String> name(scope, newString(QStringLiteral("thrower")));
-    thrower = newBuiltinFunction(rootContext, name.getPointer(), throwTypeError)->getPointer();
+    thrower = ScopedFunctionObject(scope, BuiltinFunction::create(rootContext, name.getPointer(), throwTypeError)).getPointer();
 }
 
 ExecutionEngine::~ExecutionEngine()
@@ -481,20 +481,6 @@ ExecutionContext *ExecutionEngine::pushGlobalContext()
     return g;
 }
 
-Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
-{
-    BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code);
-    return f->asReturned<FunctionObject>();
-}
-
-Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs)
-{
-    Q_ASSERT(target);
-
-    BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs);
-    return f->asReturned<BoundFunction>();
-}
-
 
 Returned<Object> *ExecutionEngine::newObject()
 {
index 12434db..6849acc 100644 (file)
@@ -307,9 +307,6 @@ public:
     void pushContext(CallContext *context);
     ExecutionContext *popContext();
 
-    Returned<FunctionObject> *newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *));
-    Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs);
-
     Returned<Object> *newObject();
     Returned<Object> *newObject(InternalClass *internalClass);
 
index 38b2dcb..c3b4860 100644 (file)
@@ -215,20 +215,20 @@ void FunctionObject::markObjects(Managed *that, ExecutionEngine *e)
     Object::markObjects(that, e);
 }
 
-FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
+FunctionObject::Data *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
 {
     if (function->needsActivation() ||
         function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
         function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount ||
         function->isNamedExpression())
-        return new (scope->d()->engine->memoryManager) ScriptFunction(scope, function);
-    return new (scope->d()->engine->memoryManager) SimpleScriptFunction(scope, function, createProto);
+        return new (scope->d()->engine) ScriptFunction::Data(scope, function);
+    return new (scope->d()->engine) SimpleScriptFunction::Data(scope, function, createProto);
 }
 
 DEFINE_OBJECT_VTABLE(FunctionCtor);
 
-FunctionCtor::FunctionCtor(ExecutionContext *scope)
-    : FunctionObject(scope, QStringLiteral("Function"))
+FunctionCtor::Data::Data(ExecutionContext *scope)
+    : FunctionObject::Data(scope, QStringLiteral("Function"))
 {
     setVTable(staticVTable());
 }
@@ -392,30 +392,15 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
     }
     ScopedValue protectBoundArgs(scope, boundArgs.d());
 
-    return ctx->d()->engine->newBoundFunction(ctx->d()->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
+    return BoundFunction::create(ctx->d()->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
 }
 
 DEFINE_OBJECT_VTABLE(ScriptFunction);
 
-ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
-    : SimpleScriptFunction(scope, function, true)
+ScriptFunction::Data::Data(ExecutionContext *scope, Function *function)
+    : SimpleScriptFunction::Data(scope, function, true)
 {
     setVTable(staticVTable());
-
-    Scope s(scope);
-    ScopedValue protectThis(s, this);
-
-    d()->needsActivation = function->needsActivation();
-    d()->strictMode = function->isStrict();
-
-    defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(formalParameterCount()));
-
-    if (scope->d()->strictMode) {
-        ExecutionEngine *v4 = scope->engine;
-        Property pd(v4->thrower, v4->thrower);
-        insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-        insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-    }
 }
 
 ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
@@ -470,34 +455,32 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
 
 DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
 
-SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
-    : FunctionObject(scope, function->name(), createProto)
+SimpleScriptFunction::Data::Data(ExecutionContext *scope, Function *function, bool createProto)
+    : FunctionObject::Data(scope, function->name(), createProto)
 {
     setVTable(staticVTable());
 
-    Scope s(scope);
-    ScopedValue protectThis(s, this);
-
-    d()->function = function;
-    d()->function->compilationUnit->ref();
+    this->function = function;
+    function->compilationUnit->ref();
     Q_ASSERT(function);
     Q_ASSERT(function->code);
 
+    needsActivation = function->needsActivation();
+    strictMode = function->isStrict();
+
     // global function
     if (!scope)
         return;
 
-    ExecutionEngine *v4 = scope->d()->engine;
-
-    d()->needsActivation = function->needsActivation();
-    d()->strictMode = function->isStrict();
+    Scope s(scope);
+    ScopedFunctionObject f(s, this);
 
-    defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(formalParameterCount()));
+    f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
 
     if (scope->d()->strictMode) {
-        Property pd(v4->thrower, v4->thrower);
-        insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-        insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+        Property pd(s.engine->thrower, s.engine->thrower);
+        f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+        f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
     }
 }
 
@@ -594,10 +577,10 @@ InternalClass *SimpleScriptFunction::internalClassForConstructor()
 
 DEFINE_OBJECT_VTABLE(BuiltinFunction);
 
-BuiltinFunction::BuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
-    : FunctionObject(scope, name)
+BuiltinFunction::Data::Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+    : FunctionObject::Data(scope, name)
+    , code(code)
 {
-    d()->code = code;
     setVTable(staticVTable());
 }
 
@@ -648,36 +631,30 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
 
 DEFINE_OBJECT_VTABLE(BoundFunction);
 
-BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs)
-    : FunctionObject(scope, QStringLiteral("__bound function__"))
+BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs)
+    : FunctionObject::Data(scope, QStringLiteral("__bound function__"))
+    , target(target)
+    , boundArgs(boundArgs)
 {
-    d()->target = target;
-    d()->boundThis = boundThis;
-    d()->boundArgs = boundArgs;
-
+    this->boundThis = boundThis;
     setVTable(staticVTable());
-    setSubtype(FunctionObject::BoundFunction);
+    subtype = FunctionObject::BoundFunction;
 
     Scope s(scope);
-    ScopedValue protectThis(s, this);
+    ScopedObject f(s, this);
 
-    ScopedValue l(s, target->get(scope->d()->engine->id_length));
+    ScopedValue l(s, target->get(s.engine->id_length));
     int len = l->toUInt32();
     len -= boundArgs.size();
     if (len < 0)
         len = 0;
-    defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(len));
+    f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
 
-    ExecutionEngine *v4 = scope->d()->engine;
+    ExecutionEngine *v4 = s.engine;
 
     Property pd(v4->thrower, v4->thrower);
-    insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-    insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-}
-
-void BoundFunction::destroy(Managed *that)
-{
-    static_cast<BoundFunction *>(that)->~BoundFunction();
+    f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+    f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
 }
 
 ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
index b5cc315..970df44 100644 (file)
@@ -154,7 +154,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
         return v.asFunctionObject();
     }
 
-    static FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
+    static Data *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
 
     ReturnedValue protoProperty() { return memberData()[Index_Prototype].asReturnedValue(); }
 
@@ -175,8 +175,11 @@ inline FunctionObject *value_cast(const Value &v) {
 
 struct FunctionCtor: FunctionObject
 {
+    struct Data : FunctionObject::Data {
+        Data(ExecutionContext *scope);
+    };
+
     V4_OBJECT
-    FunctionCtor(ExecutionContext *scope);
 
     static ReturnedValue construct(Managed *that, CallData *callData);
     static ReturnedValue call(Managed *that, CallData *callData);
@@ -195,6 +198,7 @@ struct FunctionPrototype: FunctionObject
 
 struct BuiltinFunction: FunctionObject {
     struct Data : FunctionObject::Data {
+        Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *));
         ReturnedValue (*code)(CallContext *);
     };
     struct {
@@ -202,7 +206,10 @@ struct BuiltinFunction: FunctionObject {
     } __data;
     V4_OBJECT
 
-    BuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *));
+    static BuiltinFunction::Data *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+    {
+        return new (scope->engine()) Data(scope, name, code);
+    }
 
     static ReturnedValue construct(Managed *, CallData *);
     static ReturnedValue call(Managed *that, CallData *callData);
@@ -237,8 +244,10 @@ struct IndexedBuiltinFunction: FunctionObject
 
 
 struct SimpleScriptFunction: FunctionObject {
+    struct Data : FunctionObject::Data {
+        Data(ExecutionContext *scope, Function *function, bool createProto);
+    };
     V4_OBJECT
-    SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto);
 
     static ReturnedValue construct(Managed *, CallData *callData);
     static ReturnedValue call(Managed *that, CallData *callData);
@@ -247,8 +256,10 @@ struct SimpleScriptFunction: FunctionObject {
 };
 
 struct ScriptFunction: SimpleScriptFunction {
+    struct Data : SimpleScriptFunction::Data {
+        Data(ExecutionContext *scope, Function *function);
+    };
     V4_OBJECT
-    ScriptFunction(ExecutionContext *scope, Function *function);
 
     static ReturnedValue construct(Managed *, CallData *callData);
     static ReturnedValue call(Managed *that, CallData *callData);
@@ -257,6 +268,7 @@ struct ScriptFunction: SimpleScriptFunction {
 
 struct BoundFunction: FunctionObject {
     struct Data : FunctionObject::Data {
+        Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs);
         FunctionObject *target;
         Value boundThis;
         Members boundArgs;
@@ -268,17 +280,18 @@ struct BoundFunction: FunctionObject {
     } __data;
     V4_OBJECT
 
+    static BoundFunction::Data *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs)
+    {
+        return new (scope->engine()) Data(scope, target, boundThis, boundArgs);
+    }
+
     FunctionObject *target() { return d()->target; }
     Value boundThis() const { return d()->boundThis; }
     Members boundArgs() const { return d()->boundArgs; }
 
-    BoundFunction(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs);
-    ~BoundFunction() {}
-
     static ReturnedValue construct(Managed *, CallData *d);
     static ReturnedValue call(Managed *that, CallData *dd);
 
-    static void destroy(Managed *);
     static void markObjects(Managed *that, ExecutionEngine *e);
 };
 
index 986ee6e..1d5350c 100644 (file)
@@ -176,10 +176,6 @@ const QV4::ObjectVTable classname::static_vtbl =    \
     advanceIterator                            \
 }
 
-struct HeapObject {
-
-};
-
 struct Q_QML_PRIVATE_EXPORT Managed
 {
     struct Data : HeapObject {
index 235519b..187e775 100644 (file)
@@ -171,7 +171,7 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
     ExecutionEngine *e = engine();
     Scope scope(e);
     ScopedString s(scope, e->newIdentifier(name));
-    Scoped<FunctionObject> function(scope, e->newBuiltinFunction(e->rootContext, s.getPointer(), code));
+    Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, s.getPointer(), code));
     function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
     defineDefaultProperty(s.getPointer(), function);
 }
@@ -180,7 +180,7 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte
 {
     ExecutionEngine *e = engine();
     Scope scope(e);
-    Scoped<FunctionObject> function(scope, e->newBuiltinFunction(e->rootContext, name, code));
+    Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, name, code));
     function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
     defineDefaultProperty(name, function);
 }
@@ -198,8 +198,8 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo
     ExecutionEngine *v4 = engine();
     QV4::Scope scope(v4);
     ScopedProperty p(scope);
-    p->setGetter(getter ? v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer() : 0);
-    p->setSetter(setter ? v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer() : 0);
+    p->setGetter(getter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, getter)).getPointer() : 0);
+    p->setSetter(setter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, setter)).getPointer() : 0);
     insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
 }
 
index 3d9d2ee..5ac90db 100644 (file)
@@ -133,8 +133,8 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
     defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
     defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
 
-    Property p(v4->newBuiltinFunction(v4->rootContext, v4->id___proto__, method_get_proto)->getPointer(),
-               v4->newBuiltinFunction(v4->rootContext, v4->id___proto__, method_set_proto)->getPointer());
+    Property p(ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_get_proto)).getPointer(),
+               ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_set_proto)).getPointer());
     insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
 }
 
index 1df2ca9..400ee69 100644 (file)
@@ -267,8 +267,7 @@ ReturnedValue Runtime::closure(ExecutionContext *ctx, int functionId)
 {
     QV4::Function *clos = ctx->d()->compilationUnit->runtimeFunctions[functionId];
     Q_ASSERT(clos);
-    FunctionObject *f = FunctionObject::createScriptFunction(ctx, clos);
-    return f->asReturnedValue();
+    return FunctionObject::createScriptFunction(ctx, clos)->asReturnedValue();
 }
 
 ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index)
index 7c4f3ec..7b49db7 100644 (file)
@@ -64,6 +64,8 @@ struct Returned : private T
     using T::asReturnedValue;
 };
 
+struct HeapObject {};
+
 struct Q_QML_PRIVATE_EXPORT Value
 {
     /*
@@ -347,6 +349,10 @@ struct Q_QML_PRIVATE_EXPORT Value
         val = Value::fromManaged(t).val;
         return *this;
     }
+    Value &operator=(HeapObject *o) {
+        m = reinterpret_cast<Managed *>(o);
+        return *this;
+    }
 
     template<typename T>
     Value &operator=(const Scoped<T> &t);
index 4d1f9f1..a9f748c 100644 (file)
@@ -235,7 +235,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
     QV4::Scoped<QV4::FunctionObject> createsendconstructor(scope, createsendscript.run());
     Q_ASSERT(!scope.engine->hasException);
     QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
-    QV4::ScopedValue function(scope, m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, name.getPointer(),
+    QV4::ScopedValue function(scope, QV4::BuiltinFunction::create(m_v4Engine->rootContext, name.getPointer(),
                                                                     QQuickWorkerScriptEnginePrivate::method_sendMessage));
     QV4::ScopedCallData callData(scope, 1);
     callData->args[0] = function;