aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp100
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h39
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp5
3 files changed, 124 insertions, 20 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index c890dc0550..b22d3073b9 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -137,14 +137,83 @@ void PropertyHash::detach(bool grow, int classSize)
d = dd;
}
+
+SharedInternalClassDataPrivate<PropertyKey>::SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate<PropertyKey> &other)
+ : refcount(1),
+ engine(other.engine),
+ data(nullptr)
+{
+ if (other.alloc()) {
+ int s = other.size();
+ data = MemberData::allocate(engine, other.alloc(), other.data);
+ setSize(s);
+ }
+}
+
+SharedInternalClassDataPrivate<PropertyKey>::SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate<PropertyKey> &other,
+ uint pos, PropertyKey value)
+ : refcount(1),
+ engine(other.engine)
+{
+ data = MemberData::allocate(engine, other.alloc(), nullptr);
+ memcpy(data, other.data, sizeof(Heap::MemberData) - sizeof(Value) + pos*sizeof(Value));
+ data->values.size = pos + 1;
+ data->values.set(engine, pos, Value::fromReturnedValue(value.id()));
+}
+
+void SharedInternalClassDataPrivate<PropertyKey>::grow()
+{
+ uint a = alloc() * 2;
+ int s = size();
+ data = MemberData::allocate(engine, a, data);
+ setSize(s);
+ Q_ASSERT(alloc() >= a);
+}
+
+uint SharedInternalClassDataPrivate<PropertyKey>::alloc() const
+{
+ return data ? data->values.alloc : 0;
+}
+
+uint SharedInternalClassDataPrivate<PropertyKey>::size() const
+{
+ return data ? data->values.size : 0;
+}
+
+void SharedInternalClassDataPrivate<PropertyKey>::setSize(uint s)
+{
+ Q_ASSERT(data && s <= alloc());
+ data->values.size = s;
+}
+
+PropertyKey SharedInternalClassDataPrivate<PropertyKey>::at(uint i)
+{
+ Q_ASSERT(data && i < size());
+ return PropertyKey::fromId(data->values.values[i].rawValue());
+}
+
+void SharedInternalClassDataPrivate<PropertyKey>::set(uint i, PropertyKey t)
+{
+ Q_ASSERT(data && i < size());
+ data->values.values[i].rawValueRef() = t.id();
+}
+
+void SharedInternalClassDataPrivate<PropertyKey>::mark(MarkStack *s)
+{
+ if (data)
+ data->mark(s);
+}
+
+
+
namespace Heap {
void InternalClass::init(ExecutionEngine *engine)
{
Base::init();
new (&propertyTable) PropertyHash();
- new (&nameMap) SharedInternalClassData<PropertyKey>();
- new (&propertyData) SharedInternalClassData<PropertyAttributes>();
+ new (&nameMap) SharedInternalClassData<PropertyKey>(engine);
+ new (&propertyData) SharedInternalClassData<PropertyAttributes>(engine);
new (&transitions) std::vector<Transition>();
this->engine = engine;
@@ -204,6 +273,11 @@ void InternalClass::destroy()
Base::destroy();
}
+QString InternalClass::keyAt(uint index) const
+{
+ return nameMap.at(index).toQString();
+}
+
static void insertHoleIntoPropertyData(QV4::Object *object, int idx)
{
Heap::Object *o = object->d();
@@ -288,8 +362,8 @@ Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, Propert
if (data.isAccessor() != propertyData.at(idx).isAccessor()) {
// this changes the layout of the class, so we need to rebuild the data
newClass->propertyTable = PropertyHash();
- newClass->nameMap = SharedInternalClassData<PropertyKey>();
- newClass->propertyData = SharedInternalClassData<PropertyAttributes>();
+ newClass->nameMap = SharedInternalClassData<PropertyKey>(engine);
+ newClass->propertyData = SharedInternalClassData<PropertyAttributes>(engine);
newClass->size = 0;
for (uint i = 0; i < size; ++i) {
PropertyKey identifier = nameMap.at(i);
@@ -423,7 +497,9 @@ Heap::InternalClass *InternalClass::addMemberImpl(PropertyKey identifier, Proper
return t.lookup;
// create a new class and add it to the tree
- Heap::InternalClass *newClass = engine->newClass(this);
+ Scope scope(engine);
+ Scoped<QV4::InternalClass> ic(scope, engine->newClass(this));
+ InternalClass *newClass = ic->d();
PropertyHash::Entry e = { identifier, newClass->size };
newClass->propertyTable.addEntry(e, newClass->size);
@@ -504,7 +580,9 @@ Heap::InternalClass *InternalClass::sealed()
return t.lookup;
}
- Heap::InternalClass *s = engine->newClass(this);
+ Scope scope(engine);
+ Scoped<QV4::InternalClass> ic(scope, engine->newClass(this));
+ Heap::InternalClass *s = ic->d();
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
@@ -550,7 +628,9 @@ Heap::InternalClass *InternalClass::frozen()
return t.lookup;
}
- Heap::InternalClass *f = engine->newClass(this);
+ Scope scope(engine);
+ Scoped<QV4::InternalClass> ic(scope, engine->newClass(this));
+ Heap::InternalClass *f = ic->d();
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
@@ -631,11 +711,7 @@ void InternalClass::markObjects(Heap::Base *b, MarkStack *stack)
if (ic->parent)
ic->parent->mark(stack);
- for (uint i = 0; i < ic->size; ++i) {
- PropertyKey id = ic->nameMap.at(i);
- if (Heap::Base *b = id.asStringOrSymbol())
- b->mark(stack);
- }
+ ic->nameMap.mark(stack);
}
}
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 8bf83d87b4..cb45343d6d 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -143,7 +143,7 @@ inline uint PropertyHash::lookup(PropertyKey identifier) const
template<typename T>
struct SharedInternalClassDataPrivate {
- SharedInternalClassDataPrivate()
+ SharedInternalClassDataPrivate(ExecutionEngine *)
: refcount(1),
m_alloc(0),
m_size(0),
@@ -159,7 +159,7 @@ struct SharedInternalClassDataPrivate {
memcpy(data, other.data, m_size*sizeof(T));
}
}
- SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, int pos, T value)
+ SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, uint pos, T value)
: refcount(1),
m_alloc(pos + 8),
m_size(pos + 1)
@@ -191,21 +191,45 @@ struct SharedInternalClassDataPrivate {
T at(uint i) { Q_ASSERT(data && i < m_alloc); return data[i]; }
void set(uint i, T t) { Q_ASSERT(data && i < m_alloc); data[i] = t; }
- int refcount;
+ void mark(MarkStack *) {}
+
+ int refcount = 1;
private:
uint m_alloc;
uint m_size;
T *data;
};
+template<>
+struct SharedInternalClassDataPrivate<PropertyKey> {
+ SharedInternalClassDataPrivate(ExecutionEngine *e) : refcount(1), engine(e), data(nullptr) {}
+ SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other);
+ SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, uint pos, PropertyKey value);
+ ~SharedInternalClassDataPrivate() {}
+
+ void grow();
+ uint alloc() const;
+ uint size() const;
+ void setSize(uint s);
+
+ PropertyKey at(uint i);
+ void set(uint i, PropertyKey t);
+
+ void mark(MarkStack *s);
+
+ int refcount = 1;
+private:
+ ExecutionEngine *engine;
+ Heap::MemberData *data;
+};
template <typename T>
struct SharedInternalClassData {
using Private = SharedInternalClassDataPrivate<T>;
Private *d;
- inline SharedInternalClassData() {
- d = new Private;
+ inline SharedInternalClassData(ExecutionEngine *e) {
+ d = new Private(e);
}
inline SharedInternalClassData(const SharedInternalClassData &other)
@@ -238,8 +262,8 @@ struct SharedInternalClassData {
Q_ASSERT(pos == d->size());
if (pos == d->alloc())
d->grow();
- d->set(pos, value);
d->setSize(d->size() + 1);
+ d->set(pos, value);
}
void set(uint pos, T value) {
@@ -262,6 +286,8 @@ struct SharedInternalClassData {
Q_ASSERT(i < d->size());
return d->at(i);
}
+
+ void mark(MarkStack *s) { d->mark(s); }
};
struct InternalClassTransition
@@ -318,6 +344,7 @@ struct InternalClass : Base {
void init(InternalClass *other);
void destroy();
+ Q_QML_PRIVATE_EXPORT QString keyAt(uint index) const;
Q_REQUIRED_RESULT InternalClass *nonExtensible();
static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index);
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index da086bd47a..246f857643 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -62,8 +62,9 @@ static size_t nextPowerOfTwo(size_t s)
Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old)
{
- Q_ASSERT(!old || old->values.size < n);
- Q_ASSERT(n);
+ Q_ASSERT(!old || old->values.size <= n);
+ if (!n)
+ n = 4;
size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value));
// round up to next power of two to avoid quadratic behaviour for very large objects