Make Managed inherit Value

This completes the first milestone towards being able to move
objects across the GC heap.

Change-Id: I8e6ce90254ea767188a31f0dc85b133534c87eb0
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2014-11-18 21:22:44 +01:00 committed by Simon Hausmann
parent 74c658bb63
commit e7b66a6058
14 changed files with 33 additions and 41 deletions

View File

@ -302,7 +302,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
QV4::ScopedContext ctx(scope, v4->currentContext());
if (ctx != v4->rootContext())
if (ctx->d() != v4->rootContext())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@ -314,7 +314,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
result = script.run();
if (scope.engine->hasException)
result = v4->catchException();
if (ctx != v4->rootContext())
if (ctx->d() != v4->rootContext())
v4->popContext();
return new QJSValuePrivate(v4, result);
}

View File

@ -48,8 +48,8 @@ namespace QV4 {
static const QV4::ArrayVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
V4_MANAGED_SIZE_TEST \
const QV4::Heap::Data *d() const { return &static_cast<const QV4::Heap::Data &>(Managed::data); } \
QV4::Heap::Data *d() { return &static_cast<QV4::Heap::Data &>(Managed::data); }
const QV4::Heap::Data *d() const { return static_cast<const QV4::Heap::Data *>(m); } \
QV4::Heap::Data *d() { return static_cast<QV4::Heap::Data *>(m); }
struct ArrayData;

View File

@ -288,7 +288,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
Q_ASSERT(argumentsObjectClass->vtable == ArgumentsObject::staticVTable());
Q_ASSERT(strictArgumentsObjectClass->vtable == ArgumentsObject::staticVTable());
m_globalObject = ScopedObject(scope, newObject()).getPointer();
m_globalObject = newObject();
Q_ASSERT(globalObject()->internalClass()->vtable);
initRootContext();

View File

@ -110,8 +110,8 @@ public:
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
Object *m_globalObject;
Object *globalObject() { return m_globalObject; }
Value m_globalObject;
Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); }
Function *globalCode;

View File

@ -586,8 +586,9 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
Q_ASSERT(v4->currentContext() == &ctx);
Scoped<CallContext> sctx(scope, &ctx);
return f->d()->code(reinterpret_cast<CallContext *>(&ctx));
return f->d()->code(sctx);
}
ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
@ -605,8 +606,9 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
Q_ASSERT(v4->currentContext() == &ctx);
Scoped<CallContext> sctx(scope, &ctx);
return f->d()->code(reinterpret_cast<CallContext *>(&ctx), f->d()->index);
return f->d()->code(sctx, f->d()->index);
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);

View File

@ -68,7 +68,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
static const QV4::ManagedVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
V4_MANAGED_SIZE_TEST \
QV4::Heap::DataClass *d() const { return &static_cast<QV4::Heap::DataClass &>(const_cast<QV4::Heap::Base &>(Managed::data)); }
QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
#define V4_OBJECT(superClass) \
public: \
@ -77,7 +77,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
static const QV4::ObjectVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
V4_MANAGED_SIZE_TEST \
Data *d() const { return &static_cast<Data &>(const_cast<QV4::Heap::Base &>(Managed::data)); }
Data *d() const { return static_cast<Data *>(m); }
#define V4_OBJECT2(DataClass, superClass) \
public: \
@ -87,7 +87,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
static const QV4::ObjectVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
V4_MANAGED_SIZE_TEST \
QV4::Heap::DataClass *d() const { return &static_cast<QV4::Heap::DataClass &>(const_cast<QV4::Heap::Base &>(Managed::data)); }
QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
#define Q_MANAGED_TYPE(type) \
public: \
@ -182,9 +182,8 @@ const QV4::ObjectVTable classname::static_vtbl = \
advanceIterator \
}
struct Q_QML_PRIVATE_EXPORT Managed
struct Q_QML_PRIVATE_EXPORT Managed : Value
{
Heap::Base data;
V4_MANAGED(Base, Managed)
enum {
IsExecutionContext = false,
@ -196,12 +195,9 @@ struct Q_QML_PRIVATE_EXPORT Managed
};
private:
void *operator new(size_t);
Managed();
Managed(const Managed &other);
void operator = (const Managed &other);
Managed(InternalClass *internal)
: data(internal)
{
}
void *operator new(size_t size, MemoryManager *mm);
void *operator new(size_t, Managed *m) { return m; }
@ -339,14 +335,7 @@ inline Value Value::fromManaged(Managed *m)
{
if (!m)
return QV4::Primitive::undefinedValue();
Value v;
#if QT_POINTER_SIZE == 8
v.m = &m->data;
#else
v.tag = Managed_Type;
v.m = &m->data;
#endif
return v;
return *m;
}
}

View File

@ -56,7 +56,7 @@ Heap::MemberData *MemberData::reallocate(ExecutionEngine *e, Heap::MemberData *o
Scope scope(e);
Scoped<MemberData> newMemberData(scope, static_cast<Heap::MemberData *>(e->memoryManager->allocManaged(alloc)));
if (old)
memcpy(newMemberData, old, sizeof(Heap::MemberData) + s*sizeof(Value));
memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + s*sizeof(Value));
else
new (newMemberData->d()) Heap::MemberData(e->memberDataClass);
newMemberData->d()->size = newAlloc;

View File

@ -52,7 +52,7 @@ DEFINE_OBJECT_VTABLE(Object);
Heap::Object::Object(InternalClass *internalClass, QV4::Object *prototype)
: Heap::Base(internalClass),
prototype(prototype->d())
prototype(prototype ? prototype->d() : 0)
{
if (internalClass->size) {
Scope scope(internalClass->engine);

View File

@ -64,8 +64,8 @@ ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
void ObjectIterator::init(Object *o)
{
object->m = o ? &o->data : 0;
current->m = o ? &o->data : 0;
object->m = o ? o->m : 0;
current->m = o ? o->m : 0;
#if QT_POINTER_SIZE == 4
object->tag = QV4::Value::Managed_Type;

View File

@ -206,9 +206,9 @@ struct Scoped
inline void setPointer(Managed *p) {
#if QT_POINTER_SIZE == 8
ptr->val = (quint64)(p ? &p->data : 0);
ptr->m = p ? p->m : 0;
#else
*ptr = p ? QV4::Value::fromManaged(p) : QV4::Primitive::undefinedValue();
*ptr = QV4::Value::fromManaged(p);
#endif
}
@ -437,7 +437,7 @@ inline Value &Value::operator=(const ValueRef v)
template<typename T>
inline TypedValue<T> &TypedValue<T>::operator =(T *t)
{
m = t ? &t->data : 0;
m = t ? t->m : 0;
#if QT_POINTER_SIZE == 4
tag = Managed_Type;
#endif

View File

@ -49,13 +49,13 @@ inline bool Value::isString() const
{
if (!isManaged())
return false;
return m && static_cast<Heap::Base *>(m)->internalClass->vtable->isString;
return m && m->internalClass->vtable->isString;
}
inline bool Value::isObject() const
{
if (!isManaged())
return false;
return m && static_cast<Heap::Base *>(m)->internalClass->vtable->isObject;
return m && m->internalClass->vtable->isObject;
}
inline bool Value::isPrimitive() const

View File

@ -301,13 +301,13 @@ struct Q_QML_PRIVATE_EXPORT Value
}
String *stringValue() const {
return m ? reinterpret_cast<String*>(m) : 0;
return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
}
Object *objectValue() const {
return m ? reinterpret_cast<Object*>(m) : 0;
return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
}
Managed *managed() const {
return m ? reinterpret_cast<Managed*>(m) : 0;
return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
}
Heap::Base *heapObject() const {
return m;

View File

@ -145,7 +145,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
QV4::Scope scope(engine);
QV4::ScopedContext context(scope, engine->currentContext());
context->d()->lineNumber = -1;
engine->currentContext()->lineNumber = -1;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
@ -616,14 +616,14 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
context->d()->lineNumber = instr.lineNumber;
engine->currentContext()->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
context->d()->lineNumber = instr.lineNumber;
engine->currentContext()->lineNumber = instr.lineNumber;
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(LoadThis)

View File

@ -1838,6 +1838,7 @@ void tst_QJSEngine::errorConstructors()
QJSValue ret = eng.evaluate(code);
QVERIFY(ret.isError());
QVERIFY(ret.toString().startsWith(name));
qDebug() << ret.property("stack").toString();
QCOMPARE(ret.property("lineNumber").toInt(), i+2);
}
}