From 47bf40dd49f90b52cc1b545b2be3035d48d6199e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 19 Sep 2013 16:05:25 +0200 Subject: 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 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arrayobject.cpp | 2 +- src/qml/jsruntime/qv4booleanobject.cpp | 2 +- src/qml/jsruntime/qv4dateobject.cpp | 2 +- src/qml/jsruntime/qv4engine.cpp | 2 +- src/qml/jsruntime/qv4errorobject.cpp | 29 +++++++---- src/qml/jsruntime/qv4errorobject_p.h | 2 +- src/qml/jsruntime/qv4function.cpp | 7 ++- src/qml/jsruntime/qv4function_p.h | 2 +- src/qml/jsruntime/qv4functionobject.cpp | 89 ++++++++++++++++++++++++--------- src/qml/jsruntime/qv4functionobject_p.h | 11 ++-- src/qml/jsruntime/qv4mm.cpp | 17 ++++--- src/qml/jsruntime/qv4numberobject.cpp | 2 +- src/qml/jsruntime/qv4object.cpp | 2 + src/qml/jsruntime/qv4objectproto.cpp | 2 +- src/qml/jsruntime/qv4regexpobject.cpp | 4 +- src/qml/jsruntime/qv4scopedvalue_p.h | 28 ++++++++++- src/qml/jsruntime/qv4stringobject.cpp | 2 +- src/qml/jsruntime/qv4value_def_p.h | 1 + src/qml/qml/qqmlxmlhttprequest.cpp | 6 ++- 19 files changed, 150 insertions(+), 62 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index aa9b6af728..492dfe139b 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -49,7 +49,7 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(ArrayCtor); ArrayCtor::ArrayCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("Array"))) + : FunctionObject(scope, QStringLiteral("Array")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 44188e535c..be801a67c2 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -46,7 +46,7 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(BooleanCtor); BooleanCtor::BooleanCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier("Boolean")) + : FunctionObject(scope, QStringLiteral("Boolean")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 72dc5433e5..8bc92c6c4e 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -652,7 +652,7 @@ QDateTime DateObject::toQDateTime() const DEFINE_MANAGED_VTABLE(DateCtor); DateCtor::DateCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("Date"))) + : FunctionObject(scope, QStringLiteral("Date")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 8d85ffd4fc..821e88ee61 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -358,7 +358,7 @@ ExecutionContext *ExecutionEngine::pushGlobalContext() Returned *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(SimpleCallContext *)) { - BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name.getPointer(), code); + BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code); return f->asReturned(); } diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 700e17c664..7ffc4feb9e 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -78,6 +78,10 @@ ErrorObject::ErrorObject(InternalClass *ic) { type = Type_ErrorObject; vtbl = &static_vtbl; + + Scope scope(engine()); + ScopedValue protectThis(scope, this); + defineDefaultProperty(QStringLiteral("name"), Value::fromString(ic->engine, "Error")); } @@ -88,6 +92,10 @@ ErrorObject::ErrorObject(InternalClass *ic, const Value &message, ErrorType t) type = Type_ErrorObject; vtbl = &static_vtbl; subtype = t; + + Scope scope(engine()); + ScopedValue protectThis(scope, this); + defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); if (!message.isUndefined()) @@ -108,8 +116,11 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QStrin type = Type_ErrorObject; vtbl = &static_vtbl; subtype = t; - defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); + Scope scope(engine()); + ScopedValue protectThis(scope, this); + + defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); defineDefaultProperty(QStringLiteral("name"), Value::fromString(ic->engine, className())); stackTrace = ic->engine->stackTrace(); @@ -229,12 +240,12 @@ DEFINE_MANAGED_VTABLE(TypeErrorCtor); DEFINE_MANAGED_VTABLE(URIErrorCtor); ErrorCtor::ErrorCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("Error"))) + : FunctionObject(scope, QStringLiteral("Error")) { vtbl = &static_vtbl; } -ErrorCtor::ErrorCtor(ExecutionContext *scope, String *name) +ErrorCtor::ErrorCtor(ExecutionContext *scope, const QString &name) : FunctionObject(scope, name) { vtbl = &static_vtbl; @@ -251,7 +262,7 @@ ReturnedValue ErrorCtor::call(Managed *that, CallData *callData) } EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, scope->engine->newIdentifier("EvalError")) + : ErrorCtor(scope, QStringLiteral("EvalError")) { vtbl = &static_vtbl; } @@ -263,7 +274,7 @@ ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData) } RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, scope->engine->newIdentifier("RangeError")) + : ErrorCtor(scope, QStringLiteral("RangeError")) { vtbl = &static_vtbl; } @@ -274,7 +285,7 @@ ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData) } ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, scope->engine->newIdentifier("ReferenceError")) + : ErrorCtor(scope, QStringLiteral("ReferenceError")) { vtbl = &static_vtbl; } @@ -285,7 +296,7 @@ ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData) } SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, scope->engine->newIdentifier("SyntaxError")) + : ErrorCtor(scope, QStringLiteral("SyntaxError")) { vtbl = &static_vtbl; } @@ -296,7 +307,7 @@ ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData) } TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, scope->engine->newIdentifier("TypeError")) + : ErrorCtor(scope, QStringLiteral("TypeError")) { vtbl = &static_vtbl; } @@ -307,7 +318,7 @@ ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData) } URIErrorCtor::URIErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, scope->engine->newIdentifier("URIError")) + : ErrorCtor(scope, QStringLiteral("URIError")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index fb526e9b1e..1592ec791e 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -116,7 +116,7 @@ struct ErrorCtor: FunctionObject { Q_MANAGED ErrorCtor(ExecutionContext *scope); - ErrorCtor(ExecutionContext *scope, String *name); + ErrorCtor(ExecutionContext *scope, const QString &name); static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index f69a095991..a39050aaf2 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -53,8 +53,7 @@ using namespace QV4; Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, ReturnedValue (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize) - : name(0) - , compiledFunction(function) + : compiledFunction(function) , compilationUnit(unit) , codePtr(codePtr) , codeData(0) @@ -81,8 +80,8 @@ Function::~Function() void Function::mark() { - if (name) - name->mark(); + if (name.asManaged()) + name.asManaged()->mark(); for (int i = 0; i < formals.size(); ++i) formals.at(i)->mark(); for (int i = 0; i < locals.size(); ++i) diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index b93eded3f3..746abe910d 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -81,7 +81,7 @@ struct InternalClass; struct Lookup; struct Function { - String *name; + SafeString name; const CompiledData::Function *compiledFunction; CompiledData::CompilationUnit *compilationUnit; 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 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 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(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) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index dfd160dbc0..d01a989ae1 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -106,16 +106,19 @@ struct Q_QML_EXPORT FunctionObject: Object { }; ExecutionContext *scope; - String *name; + SafeString name; String * const *formalParameterList; String * const *varList; unsigned int formalParameterCount; unsigned int varCount; Function *function; - FunctionObject(ExecutionContext *scope, String *name = 0, bool createProto = false); + FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto = false); + FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); ~FunctionObject(); + void init(const StringRef name, bool createProto); + ReturnedValue newInstance(); static ReturnedValue construct(Managed *that, CallData *); @@ -171,7 +174,7 @@ struct BuiltinFunction: FunctionObject { Q_MANAGED ReturnedValue (*code)(SimpleCallContext *); - BuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *)); + BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(SimpleCallContext *)); static ReturnedValue construct(Managed *, CallData *); static ReturnedValue call(Managed *that, CallData *callData); @@ -185,7 +188,7 @@ struct IndexedBuiltinFunction: FunctionObject uint index; IndexedBuiltinFunction(ExecutionContext *scope, uint index, ReturnedValue (*code)(SimpleCallContext *ctx, uint index)) - : FunctionObject(scope, /*name*/0) + : FunctionObject(scope) , code(code) , index(index) { diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index a7e485a2a2..0233af29b9 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -80,6 +80,7 @@ struct MemoryManager::Data bool gcBlocked; bool scribble; bool aggressiveGC; + bool exactGC; ExecutionEngine *engine; quintptr *stackTop; @@ -113,6 +114,11 @@ struct MemoryManager::Data memset(allocCount, 0, sizeof(allocCount)); scribble = !qgetenv("MM_SCRIBBLE").isEmpty(); aggressiveGC = !qgetenv("MM_AGGRESSIVE_GC").isEmpty(); + exactGC = !qgetenv("MM_EXACT_GC").isEmpty(); + if (aggressiveGC) + qDebug() << "Using aggressive garbage collection"; + if (exactGC) + qDebug() << "Using exact garbage collection"; } ~Data() @@ -293,9 +299,11 @@ void MemoryManager::mark() # endif // CPU #endif // COMPILER - collectFromStack(); collectFromJSStack(); + if (!m_d->exactGC) + collectFromStack(); + // Preserve QObject ownership rules within JavaScript: A parent with c++ ownership // keeps all of its children alive in JavaScript. @@ -573,12 +581,7 @@ void MemoryManager::collectFromStack() const assert(i == m_d->heapChunks.count() * 2); for (; current < m_d->stackTop; ++current) { - char* genericPtr = -#if QT_POINTER_SIZE == 8 - reinterpret_cast((*current) & ~(quint64(Value::Type_Mask) << Value::Tag_Shift)); -#else - reinterpret_cast(*current); -#endif + char* genericPtr = reinterpret_cast(*current); if (genericPtr < *heapChunkBoundaries || genericPtr > *(heapChunkBoundariesEnd - 1)) continue; diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 8fbc2f4d11..f946b3180a 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -51,7 +51,7 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(NumberCtor); NumberCtor::NumberCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("Number"))) + : FunctionObject(scope, QStringLiteral("Number")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index e356b653e6..c2a120c7f3 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1440,6 +1440,8 @@ ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) : Object(engine->arrayClass) { init(engine); + Scope scope(engine); + ScopedValue protectThis(scope, this); // Converts a QStringList to JS. // The result is a new Array object with length equal to the length diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index d0845735ce..0da2bf60b3 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -74,7 +74,7 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(ObjectCtor); ObjectCtor::ObjectCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("Object"))) + : FunctionObject(scope, QStringLiteral("Object")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index efe3c1fe71..697d5e35d6 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -143,6 +143,8 @@ void RegExpObject::init(ExecutionEngine *engine) type = Type_RegExpObject; Scope scope(engine); + ScopedObject protectThis(scope, this); + ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex"))); Property *lastIndexProperty = insertMember(lastIndex, Attr_NotEnumerable|Attr_NotConfigurable); lastIndexProperty->value = Value::fromInt32(0); @@ -228,7 +230,7 @@ uint RegExpObject::flags() const DEFINE_MANAGED_VTABLE(RegExpCtor); RegExpCtor::RegExpCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("RegExp"))) + : FunctionObject(scope, QStringLiteral("RegExp")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 5ec0497f15..09851af091 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -54,7 +54,7 @@ namespace QV4 { struct ScopedValue; struct Scope { - Scope(ExecutionContext *ctx) + explicit Scope(ExecutionContext *ctx) : engine(ctx->engine) #ifndef QT_NO_DEBUG , size(0) @@ -63,14 +63,17 @@ struct Scope { mark = ctx->engine->jsStackTop; } - Scope(ExecutionEngine *e) + explicit Scope(ExecutionEngine *e) : engine(e) { mark = e->jsStackTop; } ~Scope() { +#ifndef QT_NO_DEBUG Q_ASSERT(engine->jsStackTop >= mark); + memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value)); +#endif engine->jsStackTop = mark; } @@ -103,6 +106,15 @@ struct ScopedValue #endif } + ScopedValue(const Scope &scope, Managed *m) + { + ptr = scope.engine->jsStackTop++; + ptr->val = m->asReturnedValue(); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + ScopedValue(const Scope &scope, const ReturnedValue &v) { ptr = scope.engine->jsStackTop++; @@ -127,6 +139,11 @@ struct ScopedValue return *this; } + ScopedValue &operator=(Managed *m) { + ptr->val = m->asReturnedValue(); + return *this; + } + ScopedValue &operator=(const ReturnedValue &v) { ptr->val = v; return *this; @@ -598,6 +615,13 @@ inline Safe &Safe::operator=(Returned *t) return *this; } +template +inline Safe &Safe::operator =(const Referenced &v) +{ + val = v.asReturnedValue(); + return *this; +} + template inline Safe &Safe::operator=(const Safe &t) { diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index feee229668..5e1f9161e8 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -155,7 +155,7 @@ void StringObject::markObjects(Managed *that) DEFINE_MANAGED_VTABLE(StringCtor); StringCtor::StringCtor(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->newIdentifier(QStringLiteral("String"))) + : FunctionObject(scope, QStringLiteral("String")) { vtbl = &static_vtbl; } diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h index 3e0728bcc2..bf344a7f3d 100644 --- a/src/qml/jsruntime/qv4value_def_p.h +++ b/src/qml/jsruntime/qv4value_def_p.h @@ -366,6 +366,7 @@ struct Safe : public Value { Safe &operator =(T *t); Safe &operator =(const Scoped &v); + Safe &operator =(const Referenced &v); Safe &operator =(Returned *t); Safe &operator =(const Safe &t); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 79b9344994..48072f53c8 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1585,9 +1585,12 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject { Q_MANAGED QQmlXMLHttpRequestCtor(ExecutionEngine *engine) - : FunctionObject(engine->rootContext, engine->newString(QStringLiteral("XMLHttpRequest"))) + : FunctionObject(engine->rootContext, QStringLiteral("XMLHttpRequest")) { vtbl = &static_vtbl; + Scope scope(engine); + ScopedValue protectThis(scope, this); + defineReadonlyProperty(QStringLiteral("UNSENT"), Value::fromInt32(0)); defineReadonlyProperty(QStringLiteral("OPENED"), Value::fromInt32(1)); defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Value::fromInt32(2)); @@ -1595,7 +1598,6 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject defineReadonlyProperty(QStringLiteral("DONE"), Value::fromInt32(4)); if (!proto) setupProto(); - Scope scope(engine); ScopedString s(scope, engine->id_prototype); defineDefaultProperty(s, Value::fromObject(proto)); } -- cgit v1.2.3