[Development] Storing and managing ValueArray inside QV4::Heap objects

Valery Kotov kotov.valery at gmail.com
Tue Aug 21 07:26:27 CEST 2018


Hello Lars,

> Yes, you’re right that will be problematic, as SimpleArrayData is meant
to be used together with the Object it belongs to. So either use an
ArrayObject, or a QVector then.
I decided to give ArrayObject a try and it seems to work fine. Thank you! =)

Sincerely yours,
Valery Kotov


On Mon, 20 Aug 2018 at 09:04, Lars Knoll <lars.knoll at qt.io> wrote:

> Hi Valery,
>
> On 16 Aug 2018, at 08:06, Valery Kotov <kotov.valery at gmail.com> wrote:
>
> Hello all,
>
> I'm trying to wrap my head around SimpleArrayData API. And I might
> actually need a bit of help here.
>
> Instead of using ValueArray now I declare myValues to be SimpleArrayData*:
>
> #define MyObjectMembers(class, Member) \
>     Member(class, Pointer, SimpleArrayData*, myValues)
>
> DECLARE_HEAP_OBJECT(MyObject, Object) {
>     DECLARE_MARKOBJECTS(MyObject);
>
> In MyObjects' init function I'm creating and initializing myValues:
>
> const size_t size = sizeof(Heap::ArrayData) + length*sizeof(Value); // I
> still can have 0 length array, right?
> Heap::SimpleArrayData *d =
> e->memoryManager->allocManaged<QV4::SimpleArrayData>(size);
> d->init();
> d->type = Heap::ArrayData::Simple;
> d->offset = 0;
> d->values.alloc = length;
> d->values.size = length;
> myValues.set(e, d);
>
> Later I'm trying to add a new item to myValues:
>
> ScopedArrayObject a(scope,
> scope.engine->memoryManager->allocate<QV4::ArrayObject>());
> a->d()->arrayData.set(scope.engine, d()->myValues);
> Scoped<SimpleArrayData> sa(scope, d()->myValues);
> sa->push_front(a, newValue, 1);
>
> Clearly I'm doing something wrong. push_front adds a new item to array
> indeed, but not to myValues SimpleArrayData memeber. Internally, from what
> I could observe, realloc creates a new SimpleArrayData and new item
> actually added to it.
> What I have a little bit of trouble to understand, is how to use
> SimpleArrayData API. It has to be used in conjunction with ArrayObject
> somehow, right? Or shall I store ArrayObject pointer instead of
> SimpleArrayData?
>
>
> Yes, you’re right that will be problematic, as SimpleArrayData is meant to
> be used together with the Object it belongs to. So either use an
> ArrayObject, or a QVector then.
>
>
> >> If you have a fully dynamic array, then the alternative would be to
> store a pointer to your QVector in the heap object.
> Yes, that is a good point. Thank you. Though, I have a small concern here.
> From what I could see, QQmlSequence does not store JS heap objects in
> QVector (or did I miss it somehow?).
> Whereas I would like my container to:
> * be dynamically resizable, since amount of it's items is not known in
> advance
> * be able to store JS heap objects
>
> What would you suggest to use in this case? Shall I still go for
> SimpleArrayData and make it work? Or shall I use QVector instead? In case
> of QVector would it be safe to store JS Object pointers or it should be
> QVector of PersistentValues?
>
>
> You can use a QVector<QV4::Value>, but then you need to reimplement the
> markObjects() method manually to loop over the vector and call mark() on
> all the values.
>
> Best regards,
> Lars
>
>
> Thank you!
> Sincerely yours,
> Valery Kotov
>
>
> On Thu, 9 Aug 2018 at 08:20, Valery Kotov <kotov.valery at gmail.com> wrote:
>
>> Hi Lars, Simon,
>>
>> I think I got it. Thanks a lot for your tips!
>>
>> Sincerely yours,
>> Valery Kotov
>>
>> On 8 August 2018 at 09:32, Simon Hausmann <Simon.Hausmann at qt.io> wrote:
>>
>>> Hi,
>>>
>>> If you want to use the ValueArray, then you need to make sure that it's
>>> the last member of your type. Then encapsulate the creation if the type in
>>> a factory function that works a bit like ExecutionContext::newCallContext:
>>>
>>>     (1) Calculate how much memory you're going to need for the type
>>> _and_ the value array (minus one Value).
>>>     (2) Allocate the memory with one call to allocManaged.
>>>     (3) call init() manually.
>>>     (4) Set the alloc and size members of the value array to the amount
>>> of allocated values.
>>>
>>> While this approach is clever in the sense that it gives a compact
>>> memory representation and allocates object and array data in one shot, it
>>> also means that it's not so suitable for frequent dynamic resizing as it
>>> will require re-allocating the entire object.
>>>
>>> If you have a fully dynamic array, then the alternative would be to
>>> store a pointer to your QVector in the heap object. Heap::QQmlSequence does
>>> that, for example. Just make sure to use V4_NEEDS_DESTROY and provide a
>>> destroy() function to delete the vector.
>>>
>>> I'd probably go for the first approach with perhaps an indirect type
>>> (similar to how Object has MemberData) if the array contains references to
>>> the JS heap. If your array has only references to the C heap, then you're
>>> probably better off using a pointer to a regular vector.
>>>
>>>
>>> Simon
>>>
>>> ------------------------------
>>> *From:* Development <development-bounces+simon.hausmann=
>>> qt.io at qt-project.org> on behalf of Valery Kotov <kotov.valery at gmail.com>
>>> *Sent:* Wednesday, August 8, 2018 9:10:43 AM
>>> *To:* Qt development mailing list
>>> *Subject:* [Development] Storing and managing ValueArray inside
>>> QV4::Heap objects
>>>
>>> Hello all,
>>>
>>> I have a question about QV4 heap objects and what could be stored in
>>> them.
>>> I would like to move data structure from c++ heap to GC heap.
>>> Unfortunately, my data structure stores a pair of QLists internally.
>>> As far as I'm aware, QV4::Heap objects should be "trivially
>>> constructible", and thus, cannot store QList(s).
>>> One option would be to store QList pointer and manage it's lifecycle
>>> manually. But that does not sound like a good idea.
>>> I've noticed though, that some of qv4 types are using
>>> DECLARE_MARKOBJECTS macro. By using DECLARE_MARKOBJECTS macro and
>>> ObjectMember(s) define I can actually store a ValueArray member in my QV4
>>> heap object.
>>>
>>> #define MyObjectMembers(class, Member) \
>>>     Member(class, ValueArray, ValueArray, myValues)
>>>
>>> DECLARE_HEAP_OBJECT(MyObject, Object) {
>>>     DECLARE_MARKOBJECTS(MyObject);
>>>
>>> In this case I can refer to myValues ValueArray type inside of MyObject.
>>> Unfortunately, it is a little bit unclear to me how to manage
>>> ValueArrays.
>>> From what I can see from some examples in the code (qv4generatorobject,
>>> qv4arraydata), it seems that I need to manage ValueArray manually.
>>> What I'm missing at the moment a little bit is how the actually
>>> allocation for ValueArray.values is done.
>>> I suspect that it is probably not done via plain "new" call. Otherwise
>>> it is a little bit confusing why not just to store the pointer directly.
>>>
>>> Could you guys please give me a few hints how to go about ValueArray
>>> management?
>>>
>>> Thank you!
>>> Sincerely yours,
>>> Valery Kotov
>>>
>>
>> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20180821/9e1318d2/attachment.html>


More information about the Development mailing list