aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-09-18 09:30:45 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-22 01:06:20 +0200
commit055f71f87d5d58be2aafd6c0ef2b84d57ed48b63 (patch)
tree71f5f12e997bdcca340309cd5da81aacf0b3731f
parent2d781c4ca42f50643fa37200073a2fb2644b3806 (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.cpp12
-rw-r--r--src/qml/jsruntime/qv4engine.cpp16
-rw-r--r--src/qml/jsruntime/qv4engine_p.h3
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp27
-rw-r--r--src/qml/jsruntime/qv4global_p.h15
-rw-r--r--src/qml/jsruntime/qv4object.cpp11
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp9
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h45
-rw-r--r--src/qml/types/qquickworkerscript.cpp4
-rw-r--r--tests/manual/v4/TestExpectations1
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