From 00fa9049112385f65ccdcad02b8712a32626d20c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 9 May 2014 11:35:47 +0200 Subject: [PATCH] Convert FunctionObject derived classes to new construction scheme Change-Id: I0d43a79ed531a9d651bd00866d73113c05d95a09 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 18 +------ src/qml/jsruntime/qv4engine_p.h | 3 -- src/qml/jsruntime/qv4functionobject.cpp | 95 +++++++++++++-------------------- src/qml/jsruntime/qv4functionobject_p.h | 31 +++++++---- src/qml/jsruntime/qv4managed_p.h | 4 -- src/qml/jsruntime/qv4object.cpp | 8 +-- src/qml/jsruntime/qv4objectproto.cpp | 4 +- src/qml/jsruntime/qv4runtime.cpp | 3 +- src/qml/jsruntime/qv4value_p.h | 6 +++ src/qml/types/qquickworkerscript.cpp | 2 +- 10 files changed, 74 insertions(+), 100 deletions(-) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 84c522e..1f7d756 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -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(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 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 *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) -{ - BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code); - return f->asReturned(); -} - -Returned *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(); -} - Returned *ExecutionEngine::newObject() { diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 12434db..6849acc 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -307,9 +307,6 @@ public: void pushContext(CallContext *context); ExecutionContext *popContext(); - Returned *newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)); - Returned *newBoundFunction(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs); - Returned *newObject(); Returned *newObject(InternalClass *internalClass); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 38b2dcb..c3b4860 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -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(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) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index b5cc315..970df44 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -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); }; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 986ee6e..1d5350c 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -176,10 +176,6 @@ const QV4::ObjectVTable classname::static_vtbl = \ advanceIterator \ } -struct HeapObject { - -}; - struct Q_QML_PRIVATE_EXPORT Managed { struct Data : HeapObject { diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 235519b..187e775 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -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 function(scope, e->newBuiltinFunction(e->rootContext, s.getPointer(), code)); + Scoped 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 function(scope, e->newBuiltinFunction(e->rootContext, name, code)); + Scoped 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); } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 3d9d2ee..5ac90db 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -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); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 1df2ca9..400ee69 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -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) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 7c4f3ec..7b49db7 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -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(o); + return *this; + } template Value &operator=(const Scoped &t); diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 4d1f9f1..a9f748c 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -235,7 +235,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() QV4::Scoped 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; -- 2.7.4