diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-09-18 09:30:45 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-22 01:06:20 +0200 |
commit | 055f71f87d5d58be2aafd6c0ef2b84d57ed48b63 (patch) | |
tree | 71f5f12e997bdcca340309cd5da81aacf0b3731f | |
parent | 2d781c4ca42f50643fa37200073a2fb2644b3806 (diff) |
Introduce a Referenced<T> class to pass Objects into methods
Added some convenience typedefs (StringRef, ObjectRef, ReturnedString,
ScopedString, ...)
Used StringRef in newBuiltinFunction() for testing.
Cleaned up the duplicated code for thrower functions.
Change-Id: I7b7676690cbe70d9eabb0a5afd0d922f0be3aefd
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 27 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 45 | ||||
-rw-r--r-- | src/qml/types/qquickworkerscript.cpp | 4 | ||||
-rw-r--r-- | tests/manual/v4/TestExpectations | 1 |
10 files changed, 99 insertions, 44 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 5af2c07b1a..be4fbe60b8 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -44,12 +44,6 @@ using namespace QV4; -static ReturnedValue throwTypeError(SimpleCallContext *ctx) -{ - ctx->throwTypeError(); - return Value::undefinedValue().asReturnedValue(); -} - DEFINE_MANAGED_VTABLE(ArgumentsObject); ArgumentsObject::ArgumentsObject(CallContext *context) @@ -59,12 +53,12 @@ ArgumentsObject::ArgumentsObject(CallContext *context) type = Type_ArgumentsObject; Scope scope(context); + ExecutionEngine *v4 = context->engine; if (context->strictMode) { - internalClass = engine()->strictArgumentsObjectClass; + internalClass = v4->strictArgumentsObjectClass; - Scoped<FunctionObject> thrower(scope, context->engine->newBuiltinFunction(context, 0, throwTypeError)); - Property pd = Property::fromAccessor(thrower.getPointer(), thrower.getPointer()); + Property pd = Property::fromAccessor(v4->thrower, v4->thrower); assert(CalleePropertyIndex == internalClass->find(context->engine->id_callee)); assert(CallerPropertyIndex == internalClass->find(context->engine->id_caller)); memberData[CalleePropertyIndex] = pd; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index c9d3716469..70108aa00f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -79,6 +79,12 @@ using namespace QV4; static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1); +static ReturnedValue throwTypeError(SimpleCallContext *ctx) +{ + ctx->throwTypeError(); + return Value::undefinedValue().asReturnedValue(); +} + ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory) : memoryManager(new QV4::MemoryManager) , executableAllocator(new QV4::ExecutableAllocator) @@ -287,6 +293,10 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory) globalObject->defineDefaultProperty(rootContext, QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1); globalObject->defineDefaultProperty(rootContext, QStringLiteral("escape"), GlobalFunctions::method_escape, 1); globalObject->defineDefaultProperty(rootContext, QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1); + + Scope scope(this); + Scoped<String> name(scope, newString(QStringLiteral("thrower"))); + thrower = newBuiltinFunction(rootContext, name, throwTypeError)->getPointer(); } ExecutionEngine::~ExecutionEngine() @@ -344,9 +354,9 @@ ExecutionContext *ExecutionEngine::pushGlobalContext() return current; } -Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *)) +Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, StringRef name, ReturnedValue (*code)(SimpleCallContext *)) { - BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code); + BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name.getPointer(), code); return f->asReturned<FunctionObject>(); } @@ -721,6 +731,8 @@ void ExecutionEngine::markObjects() typeErrorCtor.mark(); uRIErrorCtor.mark(); + thrower->mark(); + if (m_qmlExtensions) m_qmlExtensions->markObjects(); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index f85fd1a6d7..5ee5e46eec 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -194,6 +194,7 @@ struct Q_QML_EXPORT ExecutionEngine InternalClass *sequenceClass; EvalFunction *evalFunction; + FunctionObject *thrower; QVector<Property> argumentsAccessors; @@ -261,7 +262,7 @@ struct Q_QML_EXPORT ExecutionEngine void pushContext(SimpleCallContext *context); ExecutionContext *popContext(); - Returned<FunctionObject> *newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *)); + Returned<FunctionObject> *newBuiltinFunction(ExecutionContext *scope, StringRef name, ReturnedValue (*code)(SimpleCallContext *)); Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector<Value> &boundArgs); Returned<Object> *newObject(); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index aa94f93461..18bf4ed6b5 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -213,8 +213,6 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope) ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) { FunctionCtor *f = static_cast<FunctionCtor *>(that); - MemoryManager::GCBlocker gcBlocker(f->engine()->memoryManager); - ExecutionContext *ctx = f->engine()->current; QString arguments; QString body; @@ -365,13 +363,6 @@ ReturnedValue FunctionPrototype::method_bind(SimpleCallContext *ctx) return ctx->engine->newBoundFunction(ctx->engine->rootContext, target.getPointer(), boundThis, boundArgs)->asReturnedValue(); } - -static ReturnedValue throwTypeError(SimpleCallContext *ctx) -{ - ctx->throwTypeError(); - return 0; -} - DEFINE_MANAGED_VTABLE(ScriptFunction); ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) @@ -387,7 +378,7 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) if (!scope) return; - MemoryManager::GCBlocker gcBlocker(scope->engine->memoryManager); + ExecutionEngine *v4 = scope->engine; needsActivation = function->needsActivation(); usesArgumentsObject = function->usesArgumentsObject(); @@ -400,9 +391,7 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) varList = function->locals.constData(); if (scope->strictMode) { - Scope s(scope); - Scoped<FunctionObject> thrower(s, scope->engine->newBuiltinFunction(scope, 0, throwTypeError)); - Property pd = Property::fromAccessor(thrower.getPointer(), thrower.getPointer()); + Property pd = Property::fromAccessor(v4->thrower, v4->thrower); *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd; *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd; } @@ -484,7 +473,7 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu if (!scope) return; - MemoryManager::GCBlocker gcBlocker(scope->engine->memoryManager); + ExecutionEngine *v4 = scope->engine; needsActivation = function->needsActivation(); usesArgumentsObject = function->usesArgumentsObject(); @@ -497,9 +486,7 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu varList = function->locals.constData(); if (scope->strictMode) { - Scope s(scope); - Scoped<FunctionObject> thrower(s, scope->engine->newBuiltinFunction(scope, 0, throwTypeError)); - Property pd = Property::fromAccessor(thrower.getPointer(), thrower.getPointer()); + Property pd = Property::fromAccessor(v4->thrower, v4->thrower); *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd; *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd; } @@ -656,9 +643,9 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObject *target, Va len = 0; defineReadonlyProperty(scope->engine->id_length, Value::fromInt32(len)); - Scope s(scope); - Scoped<FunctionObject> thrower(s, scope->engine->newBuiltinFunction(scope, 0, throwTypeError)); - Property pd = Property::fromAccessor(thrower.getPointer(), thrower.getPointer()); + ExecutionEngine *v4 = scope->engine; + + Property pd = Property::fromAccessor(v4->thrower, v4->thrower); *insertMember(scope->engine->id_arguments, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd; *insertMember(scope->engine->id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable) = pd; } diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 389468cc39..9f963f345b 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -105,11 +105,22 @@ struct QObjectWrapper; // will return it in a register on all platforms. // It will be returned in rax on x64, [eax,edx] on x86 and [r0,r1] on arm typedef quint64 ReturnedValue; -template<typename T> struct Scoped; -template<typename T> struct Returned; struct CallData; struct ScopedValue; struct ValueRef; +template<typename T> struct Scoped; +typedef Scoped<String> ScopedString; +typedef Scoped<Object> ScopedObject; +typedef Scoped<FunctionObject> ScopedFunctionObject; +template<typename T> struct Returned; +typedef Returned<String> ReturnedString; +typedef Returned<Object> ReturnedObject; +typedef Returned<FunctionObject> ReturnedFunctionObject; +template<typename T> struct Referenced; +typedef Referenced<String> StringRef; +typedef Referenced<Object> ObjectRef; +typedef Referenced<FunctionObject> FunctionObjectRef; + namespace Global { enum { diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index d55c3ad41f..fadc8f286a 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -236,7 +236,7 @@ void Object::defineDefaultProperty(ExecutionContext *context, const QString &nam Q_UNUSED(argumentCount); Scope scope(context); Scoped<String> s(scope, context->engine->newIdentifier(name)); - Scoped<FunctionObject> function(scope, context->engine->newBuiltinFunction(context, s.getPointer(), code)); + Scoped<FunctionObject> function(scope, context->engine->newBuiltinFunction(context, s, code)); function->defineReadonlyProperty(context->engine->id_length, Value::fromInt32(argumentCount)); defineDefaultProperty(s.getPointer(), function.asValue()); } @@ -246,7 +246,7 @@ void Object::defineDefaultProperty(ExecutionEngine *engine, const QString &name, Q_UNUSED(argumentCount); Scope scope(engine); Scoped<String> s(scope, engine->newIdentifier(name)); - Scoped<FunctionObject> function(scope, engine->newBuiltinFunction(engine->rootContext, s.getPointer(), code)); + Scoped<FunctionObject> function(scope, engine->newBuiltinFunction(engine->rootContext, s, code)); function->defineReadonlyProperty(engine->id_length, Value::fromInt32(argumentCount)); defineDefaultProperty(s.getPointer(), function.asValue()); } @@ -263,10 +263,13 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(Simple { ExecutionEngine *v4 = engine(); Property *p = insertMember(name, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); + + Scope scope(v4); + ScopedString s(scope, name); if (getter) - p->setGetter(v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer()); + p->setGetter(v4->newBuiltinFunction(v4->rootContext, s, getter)->getPointer()); if (setter) - p->setSetter(v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer()); + p->setSetter(v4->newBuiltinFunction(v4->rootContext, s, setter)->getPointer()); } void Object::defineReadonlyProperty(ExecutionEngine *engine, const QString &name, Value value) diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 6282657556..3b07527355 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -103,6 +103,9 @@ ReturnedValue ObjectCtor::call(Managed *m, CallData *callData) void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor) { + ExecutionEngine *v4 = ctx->engine; + Scope scope(v4); + ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_prototype, Value::fromObject(this)); ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_length, Value::fromInt32(1)); ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("getPrototypeOf"), method_getPrototypeOf, 1); @@ -129,10 +132,10 @@ void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor) defineDefaultProperty(ctx, QStringLiteral("__defineGetter__"), method_defineGetter, 2); defineDefaultProperty(ctx, QStringLiteral("__defineSetter__"), method_defineSetter, 2); - ExecutionEngine *v4 = ctx->engine; + Scoped<String> id_proto(scope, v4->id___proto__); Property *p = insertMember(v4->id___proto__, Attr_Accessor|Attr_NotEnumerable); - p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id___proto__, method_get_proto)->getPointer()); - p->setSetter(v4->newBuiltinFunction(v4->rootContext, v4->id___proto__, method_set_proto)->getPointer()); + p->setGetter(v4->newBuiltinFunction(v4->rootContext, id_proto, method_get_proto)->getPointer()); + p->setSetter(v4->newBuiltinFunction(v4->rootContext, id_proto, method_set_proto)->getPointer()); } ReturnedValue ObjectPrototype::method_getPrototypeOf(SimpleCallContext *ctx) diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 711c79eb1d..066ed88588 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -411,6 +411,51 @@ private: Value *ptr; }; + +template<typename T> +struct Referenced { + // Important: Do NOT add a copy constructor to this class + // adding a copy constructor actually changes the calling convention, ie. + // is not even binary compatible. Adding it would break assumptions made + // in the jit'ed code. + Referenced(const Scoped<T> &v) + : ptr(v.ptr) {} + Referenced &operator=(const Referenced &o) + { *ptr = *o.ptr; return *this; } + Referenced &operator=(T *t) + { ptr->val = t->asReturnedValue(); return *this; } + Referenced &operator=(const Returned<T> *t) { + ptr->val = t->getPointer()->asReturnedValue(); + return *this; + } + + operator const T *() const { + return static_cast<T*>(ptr->managed()); + } + const T *operator->() const { + return static_cast<T*>(ptr->managed()); + } + + operator T *() { + return static_cast<T*>(ptr->managed()); + } + T *operator->() { + return static_cast<T*>(ptr->managed()); + } + + T *getPointer() { + return static_cast<T *>(ptr->managed()); + } + ReturnedValue asReturnedValue() const { return ptr->val; } + +private: + Value *ptr; +}; + +typedef Referenced<String> StringRef; +typedef Referenced<Object> ObjectRef; +typedef Referenced<FunctionObject> FunctionObjectRef; + template<typename T> inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v) { diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 284888b0b1..d60f7b213d 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -232,8 +232,8 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() onmessage = QV4::Script(m_v4Engine->rootContext, CALL_ONMESSAGE_SCRIPT).run(); QV4::Script createsendscript(m_v4Engine->rootContext, SEND_MESSAGE_CREATE_SCRIPT); QV4::Scoped<QV4::FunctionObject> createsendconstructor(scope, createsendscript.run()); - - QV4::ScopedValue function(scope, m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, m_v4Engine->newString(QStringLiteral("sendMessage")), + QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage"))); + QV4::ScopedValue function(scope, m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, name, QQuickWorkerScriptEnginePrivate::method_sendMessage)); QV4::ScopedCallData callData(scope, 1); callData->args[0] = function; diff --git a/tests/manual/v4/TestExpectations b/tests/manual/v4/TestExpectations index a5270c369f..93a87f9ccc 100644 --- a/tests/manual/v4/TestExpectations +++ b/tests/manual/v4/TestExpectations @@ -6,7 +6,6 @@ 10.4.3-1-106 failing 11.2.3-3_3 failing S13_A15_T4 failing -S13.2.3_A1 failing S15.4.4.3_A1_T1 failing S15.4.4.3_A3_T1 failing S15.5.4.11_A5_T1 failing |