aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-02-03 16:28:17 +0100
committerLars Knoll <lars.knoll@qt.io>2017-03-09 08:58:46 +0000
commitdf3256b1f1eaa3ff9137ad1da36508365d978a8a (patch)
treea9d7fdb2dc49efbfd4d4809a8525b864ffb2b60c
parentae92e34a0c3e8a2df88a854081678fa35c4f6b42 (diff)
Go through proper set() functions when writing to MemberData
This is required, so we only have to add the write barrier in one place. Change-Id: I4e8bde823b30ad18f043312ac3f1ed46597b91a7 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp34
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp13
-rw-r--r--src/qml/jsruntime/qv4global_p.h1
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp26
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp20
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h10
-rw-r--r--src/qml/jsruntime/qv4object.cpp16
-rw-r--r--src/qml/jsruntime/qv4object_p.h12
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp28
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4value_p.h38
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h4
-rw-r--r--src/qml/memory/qv4mmdefs_p.h8
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp54
18 files changed, 166 insertions, 134 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 4a83c4e8dc..318db4f904 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -61,20 +61,20 @@ void Heap::ArgumentsObject::init(QV4::CallContext *context)
if (context->d()->strictMode) {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller()));
- *args->propertyData(CalleePropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
- *args->propertyData(CalleePropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
- *args->propertyData(CallerPropertyIndex + QV4::Object::GetterOffset) = v4->thrower();
- *args->propertyData(CallerPropertyIndex + QV4::Object::SetterOffset) = v4->thrower();
+ args->setProperty(CalleePropertyIndex + QV4::Object::GetterOffset, *v4->thrower());
+ args->setProperty(CalleePropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
+ args->setProperty(CallerPropertyIndex + QV4::Object::GetterOffset, *v4->thrower());
+ args->setProperty(CallerPropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
args->arrayReserve(context->argc());
args->arrayPut(0, context->args(), context->argc());
args->d()->fullyCreated = true;
} else {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee()));
- *args->propertyData(CalleePropertyIndex) = context->d()->function->asReturnedValue();
+ args->setProperty(CalleePropertyIndex, context->d()->function);
}
Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length()));
- *args->propertyData(LengthPropertyIndex) = Primitive::fromInt32(context->d()->callData->argc);
+ args->setProperty(LengthPropertyIndex, Primitive::fromInt32(context->d()->callData->argc));
}
void ArgumentsObject::fullyCreate()
@@ -92,7 +92,7 @@ void ArgumentsObject::fullyCreate()
if (numAccessors) {
d()->mappedArguments.set(scope.engine, md->allocate(engine(), numAccessors));
for (uint i = 0; i < numAccessors; ++i) {
- d()->mappedArguments->values[i] = context()->callData->args[i];
+ d()->mappedArguments->values.set(scope.engine, i, context()->callData->args[i]);
arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
}
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index daa4f2d9a6..58742a0b84 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -78,10 +78,10 @@ void Heap::ErrorObject::init()
if (internalClass == scope.engine->errorProtoClass)
return;
- *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
- *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
- *propertyData(QV4::ErrorObject::Index_FileName) = Encode::undefined();
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined();
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Primitive::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_FileName, Primitive::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Primitive::undefinedValue());
}
void Heap::ErrorObject::init(const Value &message, ErrorType t)
@@ -92,17 +92,17 @@ void Heap::ErrorObject::init(const Value &message, ErrorType t)
Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
- *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Primitive::undefinedValue());
e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
if (!e->d()->stackTrace->isEmpty()) {
- *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source);
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line);
+ setProperty(scope.engine, QV4::ErrorObject::Index_FileName, scope.engine->newString(e->d()->stackTrace->at(0).source));
+ setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Primitive::fromInt32(e->d()->stackTrace->at(0).line));
}
if (!message.isUndefined())
- *propertyData(QV4::ErrorObject::Index_Message) = message;
+ setProperty(scope.engine, QV4::ErrorObject::Index_Message, message);
}
void Heap::ErrorObject::init(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
@@ -113,8 +113,8 @@ void Heap::ErrorObject::init(const Value &message, const QString &fileName, int
Scope scope(internalClass->engine);
Scoped<QV4::ErrorObject> e(scope, this);
- *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction();
- *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined();
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
+ setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Primitive::undefinedValue());
e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
StackFrame frame;
@@ -124,12 +124,12 @@ void Heap::ErrorObject::init(const Value &message, const QString &fileName, int
e->d()->stackTrace->prepend(frame);
if (!e->d()->stackTrace->isEmpty()) {
- *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source);
- *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line);
+ setProperty(scope.engine, QV4::ErrorObject::Index_FileName, scope.engine->newString(e->d()->stackTrace->at(0).source));
+ setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Primitive::fromInt32(e->d()->stackTrace->at(0).line));
}
if (!message.isUndefined())
- *propertyData(QV4::ErrorObject::Index_Message) = message;
+ setProperty(scope.engine, QV4::ErrorObject::Index_Message, message);
}
const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
@@ -319,9 +319,9 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, He
ScopedObject o(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (o = obj));
ctor->defineReadonlyProperty(engine->id_length(), Primitive::fromInt32(1));
- *obj->propertyData(Index_Constructor) = ctor;
- *obj->propertyData(Index_Message) = engine->id_empty();
- *obj->propertyData(Index_Name) = engine->newString(QString::fromLatin1(ErrorObject::className(t)));
+ obj->setProperty(Index_Constructor, ctor->d());
+ obj->setProperty(Index_Message, engine->id_empty()->d());
+ obj->setProperty(Index_Name, engine->newString(QString::fromLatin1(ErrorObject::className(t))));
if (t == Heap::ErrorObject::Error)
obj->defineDefaultProperty(engine->id_toString(), method_toString, 0);
}
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 55b0175a47..5c8f03dc72 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -106,7 +106,7 @@ void Heap::FunctionObject::init()
function = nullptr;
this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d());
Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype);
- *propertyData(Index_Prototype) = Encode::undefined();
+ setProperty(internalClass->engine, Index_Prototype, Primitive::undefinedValue());
}
@@ -126,10 +126,10 @@ void FunctionObject::init(String *n, bool createProto)
if (createProto) {
ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype()));
Q_ASSERT(s.engine->protoClass->find(s.engine->id_constructor()) == Heap::FunctionObject::Index_ProtoConstructor);
- *proto->propertyData(Heap::FunctionObject::Index_ProtoConstructor) = this->asReturnedValue();
- *propertyData(Heap::FunctionObject::Index_Prototype) = proto.asReturnedValue();
+ proto->setProperty(Heap::FunctionObject::Index_ProtoConstructor, d());
+ setProperty(Heap::FunctionObject::Index_Prototype, proto);
} else {
- *propertyData(Heap::FunctionObject::Index_Prototype) = Encode::undefined();
+ setProperty(Heap::FunctionObject::Index_Prototype, Primitive::undefinedValue());
}
if (n)
@@ -346,7 +346,8 @@ void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallD
if (callData->argc > 1) {
boundArgs = MemberData::allocate(scope.engine, callData->argc - 1);
boundArgs->d()->values.size = callData->argc - 1;
- memcpy(boundArgs->data(), callData->args + 1, (callData->argc - 1)*sizeof(Value));
+ for (uint i = 0; i < static_cast<uint>(callData->argc - 1); ++i)
+ boundArgs->set(scope.engine, i, callData->args[i + 1]);
}
ExecutionContext *global = scope.engine->rootContext();
@@ -426,7 +427,7 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function
ScopedString name(s, function->name());
f->init(name, true);
Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length);
- *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount());
+ setProperty(s.engine, Index_Length, Primitive::fromInt32(f->formalParameterCount()));
if (scope->d()->strictMode) {
ScopedProperty pd(s);
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index cd8fb91f7a..68418ba770 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -201,6 +201,7 @@ struct Property;
struct Value;
template<size_t> struct HeapValue;
template<size_t> struct ValueArray;
+template<size_t> struct HeapValueArray;
struct Lookup;
struct ArrayData;
struct VTable;
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index bac71b4537..9b18a5566e 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -126,26 +126,6 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
Q_ASSERT(extensible);
}
-static void insertHoleIntoPropertyData(Object *object, int idx)
-{
- int icSize = object->internalClass()->size;
- int from = idx;
- int to = from + 1;
- if (from < icSize)
- memmove(object->propertyData(to), object->propertyData(from),
- (icSize - from - 1) * sizeof(Value));
-}
-
-static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
-{
- int delta = (accessor ? 2 : 1);
- int oldSize = object->internalClass()->size + delta;
- int to = idx;
- int from = to + delta;
- if (from < oldSize)
- memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value));
-}
-
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
uint idx;
@@ -157,10 +137,10 @@ void InternalClass::changeMember(Object *object, String *string, PropertyAttribu
object->setInternalClass(newClass);
if (newClass->size > oldClass->size) {
Q_ASSERT(newClass->size == oldClass->size + 1);
- insertHoleIntoPropertyData(object, idx + 1);
+ object->d()->memberData->values.insertData(newClass->engine, idx + 1, Primitive::emptyValue());
} else if (newClass->size < oldClass->size) {
Q_ASSERT(newClass->size == oldClass->size - 1);
- removeFromPropertyData(object, idx + 1);
+ object->d()->memberData->values.removeData(newClass->engine, idx + 1);
}
}
@@ -318,7 +298,7 @@ void InternalClass::removeMember(Object *object, Identifier *id)
Q_ASSERT(object->internalClass()->size == oldClass->size - (accessor ? 2 : 1));
// remove the entry in the property data
- removeFromPropertyData(object, propIdx, accessor);
+ object->d()->memberData->values.removeData(oldClass->engine, propIdx, accessor ? 2 : 1);
t.lookup = object->internalClass();
Q_ASSERT(t.lookup);
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index bd677483b5..f322d5a001 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -59,7 +59,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
@@ -72,7 +72,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : Object::getValue(thisObject, *v, *attrs);
}
@@ -94,7 +94,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
if (index != UINT_MAX) {
level = i;
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
@@ -107,7 +107,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
index = obj->internalClass->find(name);
if (index != UINT_MAX) {
*attrs = obj->internalClass->propertyData.at(index);
- Value *v = obj->propertyData(index);
+ const Value *v = obj->propertyData(index);
return !attrs->isAccessor() ? v->asReturnedValue() : thisObject->getValue(*v, *attrs);
}
@@ -772,7 +772,7 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Va
{
Object *o = object.as<Object>();
if (o && o->internalClass() == l->classList[0]) {
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
@@ -785,7 +785,7 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, co
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
o->setInternalClass(l->classList[3]);
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
}
@@ -801,7 +801,7 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, co
Heap::Object *p = o->prototype();
if (p && p->internalClass == l->classList[1]) {
o->setInternalClass(l->classList[3]);
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
}
@@ -819,7 +819,7 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, co
p = p->prototype;
if (p && p->internalClass == l->classList[2]) {
o->setInternalClass(l->classList[3]);
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
}
@@ -834,11 +834,11 @@ void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c
Object *o = object.as<Object>();
if (o) {
if (o->internalClass() == l->classList[0]) {
- *o->propertyData(l->index) = value;
+ o->setProperty(l->index, value);
return;
}
if (o->internalClass() == l->classList[1]) {
- *o->propertyData(l->index2) = value;
+ o->setProperty(l->index2, value);
return;
}
}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 302553464e..dff7c09a4c 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -60,7 +60,7 @@ namespace QV4 {
namespace Heap {
#define MemberDataMembers(class, Member) \
- Member(class, ValueArray, ValueArray, values)
+ Member(class, ValueArray, HeapValueArray, values)
DECLARE_HEAP_OBJECT(MemberData, Base) {
DECLARE_MARK_TABLE(MemberData);
@@ -85,9 +85,11 @@ struct MemberData : Managed
bool isNull() const { return !memberData; }
};
- Value &operator[] (uint idx) { return d()->values[idx]; }
- const Value *data() const { return d()->values.v; }
- Value *data() { return d()->values.v; }
+ const Value &operator[] (uint idx) const { return d()->values[idx]; }
+ const Value *data() const { return d()->values.data(); }
+ void set(ExecutionEngine *e, uint index, Value v) { d()->values.set(e, index, v); }
+ void set(ExecutionEngine *e, uint index, Heap::Base *b) { d()->values.set(e, index, b); }
+
inline uint size() const { return d()->values.size; }
static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old = 0);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 3fe1ac71b4..ce8fdc6d6d 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -76,9 +76,9 @@ void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) con
void Object::setProperty(uint index, const Property *p)
{
- *propertyData(index) = p->value;
+ setProperty(index, p->value);
if (internalClass()->propertyData.at(index).isAccessor())
- *propertyData(index + SetterOffset) = p->set;
+ setProperty(index + SetterOffset, p->set);
}
bool Object::setPrototype(Object *proto)
@@ -117,7 +117,7 @@ bool Object::putValue(uint memberIndex, const Value &value)
PropertyAttributes attrs = ic->propertyData[memberIndex];
if (attrs.isAccessor()) {
- FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
+ const FunctionObject *set = propertyData(memberIndex + SetterOffset)->as<FunctionObject>();
if (set) {
Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
@@ -133,7 +133,7 @@ bool Object::putValue(uint memberIndex, const Value &value)
if (!attrs.isWritable())
goto reject;
- *propertyData(memberIndex) = value;
+ setProperty(memberIndex, value);
return true;
reject:
@@ -264,10 +264,10 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri
InternalClass::addMember(this, s, attributes, &idx);
if (attributes.isAccessor()) {
- *propertyData(idx + GetterOffset) = p->value;
- *propertyData(idx + SetterOffset) = p->set;
+ setProperty(idx + GetterOffset, p->value);
+ setProperty(idx + SetterOffset, p->set);
} else {
- *propertyData(idx) = p->value;
+ setProperty(idx, p->value);
}
}
@@ -526,7 +526,7 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value)
l->classList[0] = o->internalClass();
l->index = idx;
l->setter = Lookup::setter0;
- *o->propertyData(idx) = value;
+ o->setProperty(idx, value);
return;
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 3db52bf3d3..c0169ed035 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -78,8 +78,9 @@ DECLARE_HEAP_OBJECT(Object, Base) {
void init() { Base::init(); }
void destroy() { Base::destroy(); }
- const Value *propertyData(uint index) const { return memberData->values.v + index; }
- Value *propertyData(uint index) { return memberData->values.v + index; }
+ const Value *propertyData(uint index) const { return memberData->values.data() + index; }
+ void setProperty(ExecutionEngine *e, uint index, Value v) const { memberData->values.set(e, index, v); }
+ void setProperty(ExecutionEngine *e, uint index, Heap::Base *b) const { memberData->values.set(e, index, b); }
};
Q_STATIC_ASSERT(Object::markTable == ((2 << 4) | (2 << 6) | (2 << 8)));
@@ -195,13 +196,14 @@ struct Q_QML_EXPORT Object: Managed {
void setInternalClass(InternalClass *ic);
const Value *propertyData(uint index) const { return d()->propertyData(index); }
- Value *propertyData(uint index) { return d()->propertyData(index); }
Heap::ArrayData *arrayData() const { return d()->arrayData; }
void setArrayData(ArrayData *a) { d()->arrayData.set(engine(), a->d()); }
void getProperty(uint index, Property *p, PropertyAttributes *attrs) const;
void setProperty(uint index, const Property *p);
+ void setProperty(uint index, Value v) const { d()->setProperty(engine(), index, v); }
+ void setProperty(uint index, Heap::Base *b) const { d()->setProperty(engine(), index, b); }
const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(d()->vtable()); }
Heap::Object *prototype() const { return d()->prototype; }
@@ -469,7 +471,7 @@ struct ArrayObject : Object {
private:
void commonInit()
- { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); }
+ { setProperty(internalClass->engine, LengthPropertyIndex, Primitive::fromInt32(0)); }
};
}
@@ -509,7 +511,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- *propertyData(Heap::ArrayObject::LengthPropertyIndex) = Primitive::fromUInt32(l);
+ setProperty(Heap::ArrayObject::LengthPropertyIndex, Primitive::fromUInt32(l));
}
inline void Object::push_back(const Value &v)
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 7b15494ea9..f8ad11fa98 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -145,7 +145,7 @@ void Heap::RegExpObject::init(const QRegExp &re)
void RegExpObject::initProperties()
{
- *propertyData(Index_LastIndex) = Primitive::fromInt32(0);
+ setProperty(Index_LastIndex, Primitive::fromInt32(0));
Q_ASSERT(value());
@@ -157,16 +157,10 @@ void RegExpObject::initProperties()
p.replace('/', QLatin1String("\\/"));
}
- *propertyData(Index_Source) = engine()->newString(p);
- *propertyData(Index_Global) = Primitive::fromBoolean(global());
- *propertyData(Index_IgnoreCase) = Primitive::fromBoolean(value()->ignoreCase);
- *propertyData(Index_Multiline) = Primitive::fromBoolean(value()->multiLine);
-}
-
-Value *RegExpObject::lastIndexProperty()
-{
- Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex()));
- return propertyData(0);
+ setProperty(Index_Source, engine()->newString(p));
+ setProperty(Index_Global, Primitive::fromBoolean(global()));
+ setProperty(Index_IgnoreCase, Primitive::fromBoolean(value()->ignoreCase));
+ setProperty(Index_Multiline, Primitive::fromBoolean(value()->multiLine));
}
// Converts a JS RegExp to a QRegExp.
@@ -344,9 +338,9 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
RETURN_UNDEFINED();
QString s = str->toQString();
- int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0;
+ int offset = r->global() ? r->lastIndex() : 0;
if (offset < 0 || offset > s.length()) {
- *r->lastIndexProperty() = Primitive::fromInt32(0);
+ r->setLastIndex(0);
RETURN_RESULT(Encode::null());
}
@@ -357,7 +351,7 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- *r->lastIndexProperty() = Primitive::fromInt32(0);
+ r->setLastIndex(0);
RETURN_RESULT(Encode::null());
}
@@ -373,8 +367,8 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- *array->propertyData(Index_ArrayIndex) = Primitive::fromInt32(result);
- *array->propertyData(Index_ArrayInput) = str;
+ array->setProperty(Index_ArrayIndex, Primitive::fromInt32(result));
+ array->setProperty(Index_ArrayInput, str);
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch.set(scope.engine, array);
@@ -383,7 +377,7 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]);
+ r->setLastIndex(matchOffsets[1]);
scope.result = array;
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index c2eeb32b88..0fcfe93135 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -128,7 +128,15 @@ struct RegExpObject: Object {
void initProperties();
- Value *lastIndexProperty();
+ int lastIndex() const {
+ Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()));
+ return propertyData(Index_LastIndex)->toInt32();
+ }
+ void setLastIndex(int index) {
+ Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()));
+ return setProperty(Index_LastIndex, Primitive::fromInt32(index));
+ }
+
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 4459af0e66..7708b81d8a 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1311,7 +1311,7 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::
}
for (uint i = 0; i < klass->size; ++i)
- *o->propertyData(i) = *args++;
+ o->setProperty(i, *args++);
if (arrayValueCount > 0) {
ScopedValue entry(scope);
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 628c220bae..81f5c3566c 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -78,14 +78,14 @@ void Heap::StringObject::init()
Object::init();
Q_ASSERT(vtable() == QV4::StringObject::staticVTable());
string.set(internalClass->engine, internalClass->engine->id_empty()->d());
- *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0);
+ setProperty(internalClass->engine, LengthPropertyIndex, Primitive::fromInt32(0));
}
void Heap::StringObject::init(const QV4::String *str)
{
Object::init();
string.set(internalClass->engine, str->d());
- *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length());
+ setProperty(internalClass->engine, LengthPropertyIndex, Primitive::fromInt32(length()));
}
Heap::String *Heap::StringObject::getIndex(uint index) const
@@ -556,7 +556,7 @@ void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, Call
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
if (regExp->global())
- *regExp->lastIndexProperty() = Primitive::fromUInt32(0);
+ regExp->setLastIndex(0);
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 93b0dfb6d4..4c46eccbd3 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -717,6 +717,44 @@ struct HeapValue : Value {
};
template <size_t offset>
+struct HeapValueArray {
+ uint size;
+ uint alloc;
+ Value values[1];
+
+ void set(ExecutionEngine *e, uint index, Value v) {
+ Q_UNUSED(e);
+ Q_ASSERT(index < alloc);
+ values[index] = v;
+ }
+ void set(ExecutionEngine *e, uint index, Heap::Base *b) {
+ Q_UNUSED(e);
+ Q_ASSERT(index < alloc);
+ values[index] = b;
+ }
+ inline const Value &operator[] (uint index) const {
+ Q_ASSERT(index < alloc);
+ return values[index];
+ }
+ inline const Value *data() const {
+ return values;
+ }
+
+ void insertData(ExecutionEngine *e, uint index, Value v) {
+ for (uint i = size - 1; i > index; --i) {
+ values[i] = values[i - 1];
+ }
+ set(e, index, v);
+ }
+ void removeData(ExecutionEngine *e, uint index, int n = 1) {
+ Q_UNUSED(e);
+ for (uint i = index; i < size - n; ++i) {
+ values[i] = values[i + n];
+ }
+ }
+};
+
+template <size_t offset>
struct ValueArray {
uint size;
uint alloc;
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 5cab4c5386..f2ff5d307e 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -84,7 +84,7 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other)
return false;
}
-void VariantObject::addVmePropertyReference()
+void VariantObject::addVmePropertyReference() const
{
if (d()->isScarce() && ++d()->vmePropertyReferenceCount == 1) {
// remove from the ep->scarceResources list
@@ -94,7 +94,7 @@ void VariantObject::addVmePropertyReference()
}
}
-void VariantObject::removeVmePropertyReference()
+void VariantObject::removeVmePropertyReference() const
{
if (d()->isScarce() && --d()->vmePropertyReferenceCount == 0) {
// and add to the ep->scarceResources list
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index ef51b6632d..e281602bb5 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -96,8 +96,8 @@ struct VariantObject : Object
V4_PROTOTYPE(variantPrototype)
V4_NEEDS_DESTROY
- void addVmePropertyReference();
- void removeVmePropertyReference();
+ void addVmePropertyReference() const;
+ void removeVmePropertyReference() const;
static bool isEqualTo(Managed *m, Managed *other);
};
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h
index 63e51f9742..9c84a49e90 100644
--- a/src/qml/memory/qv4mmdefs_p.h
+++ b/src/qml/memory/qv4mmdefs_p.h
@@ -278,6 +278,10 @@ struct MarkFlagEvaluator<ValueArray<o>> {
static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_ValueArray) << (2*o / sizeof(quintptr));
};
template <size_t o>
+struct MarkFlagEvaluator<HeapValueArray<o>> {
+ static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_ValueArray) << (o >> 2);
+};
+template <size_t o>
struct MarkFlagEvaluator<HeapValue<o>> {
static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Value) << (2 *o / sizeof(quintptr));
};
@@ -288,7 +292,7 @@ struct MarkFlagEvaluator<HeapValue<o>> {
#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_Pointer(c, type, name) Pointer<type, 0> name;
#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_NoMark(c, type, name) type name;
#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_HeapValue(c, type, name) HeapValue<0> name;
-#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_ValueArray(c, type, name) ValueArray<0> name;
+#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_ValueArray(c, type, name) type<0> name;
#define HEAP_OBJECT_MEMBER_EXPANSION(c, gcType, type, name) \
HEAP_OBJECT_MEMBER_EXPANSION_##gcType(c, type, name)
@@ -300,7 +304,7 @@ struct MarkFlagEvaluator<HeapValue<o>> {
#define HEAP_OBJECT_MEMBER_EXPANSION_HeapValue(c, type, name) \
HeapValue<offsetof(c##OffsetStruct, name) + baseOffset> name;
#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \
- ValueArray<offsetof(c##OffsetStruct, name) + baseOffset> name;
+ type<offsetof(c##OffsetStruct, name) + baseOffset> name;
#define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \
MarkFlagEvaluator<decltype(class::name)>::value |
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 2c3476f63a..f464a099e0 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -104,8 +104,10 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
if (v4) {
QV4::Scope scope(v4);
QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value());
- if (sp)
- *(sp->data() + m_index) = QV4::Primitive::nullValue();
+ if (sp) {
+ QV4::MemberData::Index index{ sp->d(), static_cast<uint>(m_index) };
+ index.set(v4, QV4::Primitive::nullValue());
+ }
}
m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
@@ -329,7 +331,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
if (size) {
QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, size);
propertyAndMethodStorage.set(v4, data);
- std::fill(data->values.v, data->values.v + data->values.size, QV4::Encode::undefined());
+ std::fill(data->values.values, data->values.values + data->values.size, QV4::Encode::undefined());
}
// Need JS wrapper to ensure properties/methods are marked.
@@ -364,77 +366,77 @@ void QQmlVMEMetaObject::writeProperty(int id, int v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromInt32(v);
+ md->set(cache->engine, id, QV4::Primitive::fromInt32(v));
}
void QQmlVMEMetaObject::writeProperty(int id, bool v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromBoolean(v);
+ md->set(cache->engine, id, QV4::Primitive::fromBoolean(v));
}
void QQmlVMEMetaObject::writeProperty(int id, double v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::Primitive::fromDouble(v);
+ md->set(cache->engine, id, QV4::Primitive::fromDouble(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newString(v);
+ md->set(cache->engine, id, cache->engine->newString(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v)));
}
void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
- *(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
+ md->set(cache->engine, id, QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(cache->engine, v)));
QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id);
if (v && !guard) {
@@ -592,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const
if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) {
QVariant variant(qVariantFromValue(QList<QObject*>()));
v = cache->engine->newVariantObject(variant);
- *(md->data() + id) = v;
+ md->set(cache->engine, id, v);
}
return static_cast<QList<QObject *> *>(v->d()->data().data());
}
@@ -742,7 +744,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
QVariant propertyAsVariant;
- if (QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
+ if (const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
propertyAsVariant = v->d()->data();
QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], fallbackMetaType);
}
@@ -815,9 +817,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
case QV4::CompiledData::Property::Quaternion:
Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
- QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
if (!v) {
- *(md->data() + id) = cache->engine->newVariantObject(QVariant());
+ md->set(cache->engine, id, cache->engine->newVariantObject(QVariant()));
v = (md->data() + id)->as<QV4::VariantObject>();
QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data());
}
@@ -1028,7 +1030,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *oldVariant = (md->data() + id)->as<QV4::VariantObject>();
if (oldVariant)
oldVariant->removeVmePropertyReference();
@@ -1054,7 +1056,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
guard->setGuardedValue(valueObject, this, id);
// Write the value and emit change signal as appropriate.
- *(md->data() + id) = value;
+ md->set(cache->engine, id, value);
activate(object, methodOffset() + id, 0);
}
@@ -1067,7 +1069,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// Importantly, if the current value is a scarce resource, we need to ensure that it
// gets automatically released by the engine if no other references to it exist.
- QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *oldv = (md->data() + id)->as<QV4::VariantObject>();
if (oldv)
oldv->removeVmePropertyReference();
@@ -1081,7 +1083,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// Write the value and emit change signal as appropriate.
QVariant currentValue = readPropertyAsVariant(id);
- *(md->data() + id) = newv;
+ md->set(cache->engine, id, newv);
if ((currentValue.userType() != value.userType() || currentValue != value))
activate(object, methodOffset() + id, 0);
} else {
@@ -1093,14 +1095,14 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
} else {
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md) {
- QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
needActivate = (!v ||
v->d()->data().userType() != value.userType() ||
v->d()->data() != value);
if (v)
v->removeVmePropertyReference();
- *(md->data() + id) = cache->engine->newVariantObject(value);
- v = static_cast<QV4::VariantObject *>(md->data() + id);
+ md->set(cache->engine, id, cache->engine->newVariantObject(value));
+ v = static_cast<const QV4::VariantObject *>(md->data() + id);
v->addVmePropertyReference();
}
}
@@ -1139,7 +1141,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return;
- *(md->data() + methodIndex + compiledObject->nProperties) = function;
+ md->set(cache->engine, methodIndex + compiledObject->nProperties, function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) const