diff options
| author | Lars Knoll <lars.knoll@digia.com> | 2013-09-19 16:05:25 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-22 01:06:20 +0200 |
| commit | 47bf40dd49f90b52cc1b545b2be3035d48d6199e (patch) | |
| tree | 9e671c23d610822ac354e4a1399e2c805cbea599 /src/qml/jsruntime/qv4functionobject.cpp | |
| parent | 78b49cf8361b1462cc94a061916a15f0b98e27e3 (diff) | |
Prevent objects from being collected while in their constructor
While objects are being constructed, we don't have a reference to them
on the JS stack yet. So the constructor needs to protect itself against
being collected by putting the this object onto the JS stack.
Added an environment switch MM_EXACT_GC to test exact garbage
collection.
Change-Id: Ie37665a954de800359c272ffbebbe1488e7a8ace
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime/qv4functionobject.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 89 |
1 files changed, 65 insertions, 24 deletions
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 69c749f92f..a7332d65da 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -71,41 +71,36 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(FunctionObject); -FunctionObject::FunctionObject(ExecutionContext *scope, String *name, bool createProto) +FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto) : Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass) , scope(scope) - , name(name) , formalParameterList(0) , varList(0) , formalParameterCount(0) , varCount(0) , function(0) { - vtbl = &static_vtbl; - - type = Type_FunctionObject; - needsActivation = true; - usesArgumentsObject = false; - strictMode = false; -#ifndef QT_NO_DEBUG - assert(scope->next != (ExecutionContext *)0x1); -#endif - - if (createProto) { - Scope s(scope); - Scoped<Object> proto(s, scope->engine->newObject(scope->engine->protoClass)); - proto->memberData[Index_ProtoConstructor].value = Value::fromObject(this); - memberData[Index_Prototype].value = proto.asValue(); - } + init(name, createProto); +} - if (name) - defineReadonlyProperty(scope->engine->id_name, Value::fromString(name)); +FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) + : Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass) + , scope(scope) + , formalParameterList(0) + , varList(0) + , formalParameterCount(0) + , varCount(0) + , function(0) +{ + Scope s(scope); + ScopedValue protectThis(s, this); + ScopedString n(s, s.engine->newString(name)); + init(n, createProto); } FunctionObject::FunctionObject(InternalClass *ic) : Object(ic) , scope(ic->engine->rootContext) - , name(name) , formalParameterList(0) , varList(0) , formalParameterCount(0) @@ -113,8 +108,12 @@ FunctionObject::FunctionObject(InternalClass *ic) , function(0) { vtbl = &static_vtbl; + name = (QV4::String *)0; type = Type_FunctionObject; + needsActivation = false; + usesArgumentsObject = false; + strictMode = false; } FunctionObject::~FunctionObject() @@ -123,6 +122,36 @@ FunctionObject::~FunctionObject() function->compilationUnit->deref(); } +void FunctionObject::init(const StringRef n, bool createProto) +{ + vtbl = &static_vtbl; + + Scope s(engine()); + ScopedValue protectThis(s, this); + + type = Type_FunctionObject; + needsActivation = true; + usesArgumentsObject = false; + strictMode = false; +#ifndef QT_NO_DEBUG + assert(scope->next != (ExecutionContext *)0x1); +#endif + + if (createProto) { + Scoped<Object> proto(s, scope->engine->newObject(scope->engine->protoClass)); + proto->memberData[Index_ProtoConstructor].value = Value::fromObject(this); + memberData[Index_Prototype].value = proto.asValue(); + } + + if (n) { + name = n; + ScopedValue v(s, n.asReturnedValue()); + defineReadonlyProperty(scope->engine->id_name, v); + } else { + name = (QV4::String *)0; + } +} + ReturnedValue FunctionObject::newInstance() { Scope scope(engine()); @@ -177,7 +206,7 @@ ReturnedValue FunctionObject::call(Managed *, CallData *) void FunctionObject::markObjects(Managed *that) { FunctionObject *o = static_cast<FunctionObject *>(that); - if (o->name) + if (o->name.managed()) o->name->mark(); // these are marked in VM::Function: // for (uint i = 0; i < formalParameterCount; ++i) @@ -202,7 +231,7 @@ FunctionObject *FunctionObject::creatScriptFunction(ExecutionContext *scope, Fun DEFINE_MANAGED_VTABLE(FunctionCtor); FunctionCtor::FunctionCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("Function"))) + : FunctionObject(scope, QStringLiteral("Function")) { vtbl = &static_vtbl; } @@ -367,6 +396,10 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) : FunctionObject(scope, function->name, true) { vtbl = &static_vtbl; + + Scope s(scope); + ScopedValue protectThis(s, this); + this->function = function; this->function->compilationUnit->ref(); Q_ASSERT(function); @@ -462,6 +495,10 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu : FunctionObject(scope, function->name, true) { vtbl = &static_vtbl; + + Scope s(scope); + ScopedValue protectThis(s, this); + this->function = function; this->function->compilationUnit->ref(); Q_ASSERT(function); @@ -554,7 +591,7 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) DEFINE_MANAGED_VTABLE(BuiltinFunction); -BuiltinFunction::BuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *)) +BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(SimpleCallContext *)) : FunctionObject(scope, name) , code(code) { @@ -635,6 +672,10 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObject *target, Va , boundArgs(boundArgs) { vtbl = &static_vtbl; + + Scope s(scope); + ScopedValue protectThis(s, this); + int len = Value::fromReturnedValue(target->get(scope->engine->id_length)).toUInt32(); len -= boundArgs.size(); if (len < 0) |
