| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The change in a7349e6433d092398d76cafa5408753f06892cd7 reduced the
number of readbacks of reference objects by using connections to set
the dirty state only when necessary.
Establishing connections, however, comes at a cost and this introduced a
regression in the delegates_item_childrenRect QmlBench benchmark.
The mitigation introduced in this patch is to delay creating the
connection. When a reference object is created, it does not read or
create a connection but is simply marked as dirty. Only on a subsequent
read from within a different statement than the reference object's
creation's statement, does a connection get created.
This keeps the benefit of reducing unnecessary reads on objects that are
used multiple times while not spending too much on creating connections.
This brings back the benchmark to its original level of performance.
The referenceObjectChainReadsBackAsRequiredBasedOnParentSignals test
was changed to expect 8 reads instead of 4. Since all the accesses are
part of the same statement, no connection is ever created and more
reads are required than before.
The referenceObjectDoesNotFetchWithoutNotifyEventDateObject test is
reformatted to separate the assignment from the reads. Otherwise no
connection is ever created.
The referenceObjectDoesNotLeakAConnectionToTheDestroyedSignalOnANotifyBindable
test can be updated to expect 0 connections. With this change, we only
connect if the reference object is read again from a different
statement.
Amends a7349e6433d092398d76cafa5408753f06892cd7
Fixes: QTBUG-140757
Pick-to: 6.10
Change-Id: I5d02ec6266c51fbbe5f2e01405081dd5a167a833
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
| |
|
|
|
|
| |
Pick-to: 6.10
Change-Id: I489b515388f9aba9250bfb05687331c92578ca57
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
| |
|
|
|
| |
Change-Id: I71ba63cdde7c8f3e18b89a1a4e35da30202fd8e4
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This relies heavily on the documented fact that we only support trusted
QML/JS content, meaning most files are only significant, not critical.
This also extends to the handling of qmlc files (as in
compilationunitmapper), as we store them in a user owned, non-shared
cache directory – so any vulnerability there would already mean that an
attacker has write-priviledges on user data.
An exception is ArrayBuffer, which can be used with arbitrary user data,
and should create a valid QBA.
Fixes: QTBUG-136970
Pick-to: 6.10 6.9 6.8
QUIP: 23
Change-Id: I22033fe6ab4acf8362a8183e25b92331d45cb32c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`ReferenceObject::init` currently allocates connections to certain
signals to enable a reduction of the amount of reads the
`ReferenceObject` needs to perform, by using the signal to identify when
the data that is being represented was invalidated.
In particular, when the `ReferenceObject` is part of a chain that traces
back to a `Q_PROPERTY`, and that property either has a `NOTIFY` signal
or is a `BINDABLE`, a connection to the signal or a subscription to the
`BINDABLE` is activated.
When one of those is done, we further construct a connection to the
`destroyed` signal of the object that holds the property, to ensure that
a read is performed and our data is invalidated if that object is
destroyed.
The code that performs this process, in `ReferenceObject::init`, was
written with the incorrect assumption that a property either has a
`NOTIFY` signal or is `BINDABLE`, but not both.
In truth, a property might both have a `NOTIFY` signal and be a
`BINDABLE`.
When this is the case, the current code would allocate a connection to
the `destroyed` signal on the same memory block twice, once when setting
up a connection to the `NOTIFY` signal and once when subscribing to the
`BINDABLE`, without ensuring that the previously allocated connection
was disposed of.
To avoid this issue, the code that takes care of setting up the
connections is now exclusive between the two connections path, with a
priority on the `BINDABLE` subscription, as this mirrors the already
existing preference we have when dealing with bindings and is expected
to be slightly more performant.
The documentation for this connection process was modified to add a
small mention of this priority of execution.
Some defensive asserts were added to the relevant connection code, to
ensure that we can catch the construction of multiple connections at
once, which is to be considered a bug.
The code that takes care of disposing of the `destroyed` signal
connection was modified to ensure that we only take into account our
allocation strategy and not our actual connection status, which, while
they shouldn't generally be in discord, might incorrectly avoid a
necessary disposal if they would.
A comment that related to the condition for the disposal was modified to
be more precise with regards to the new condition.
Some test cases were added to `tst_qqmllanguage` to check the leak and
`BINDABLE` preference behavior.
Change-Id: Ibdc657fd857a8838797e47ff235f67cfaeec20de
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When certain types are passed over from C++ to QML, QML converts them to
a QML usable representation that keeps track of the original data.
To do so, the QML representation of the object performs read/write-backs
when required to ensure that the representation is kept in sync with the
original data, by reading the latest data from the source or writing
back changes that are performed on the QML side.
Generally, the representation on the QML side cannot know when the
original data was modified, so that it has to read the data again each
time it accesses the representation to ensure that the latest data is
available.
The reads can be very expensive. For example, the following snippet:
```
JSON.stringify(foo)
```
Where `foo` is, for example, a `QStringList`, might need to read the data
multiple times for each element in the list.
For representations that provene from a QObject's property that has a
NOTIFY signal, it is possible to cut down on the number of reads by
reading only when the data was effectively changed since the last read,
that is, the NOTIFY signal of the property was emitted.
Similarly, if the property is a BINDABLE, we can subscribe to the
BINDABLE itself to track whether a change was performed or not.
Thus, to reduce the number of reads when possible, `ReferenceObject`,
the base representation for objects that perform read/write-backs, was
modified to take into account the NOTIFY signal or BINDABLE status of a
property when referencing data that originally provenes from a
`QObject`'s property on the C++ side.
`QObjectWrapper`, `QQmlTypeWrapper`, `ReferenceObject` and
`QMLValueTYpeWrapper` were modified with the usual `Q_MANAGED_TYPE`
macro, to allow identifying instances of those objects, which is used to
enable the new implementation.
The intializer for `ReferenceObject` was modified to behave differently
when the referenced data comes from a `QObjectWrapper`, which wraps a
`QObject` provening from C++, or a `QQmlTypeWrapper`, which can wrap a
`QObject` that is a singleton or an attached property. When it is so,
and the part of the wrapped `QObject` that is referenced is a property
that has a NOTIFY signal or is a BINDABLE, the `ReferenceObject`
instance will now connect to the signal or subscribe to the BINDABLE.
A newly added flag, `isDirty`, will be set when the signal is emitted
and is used to track whether the data has changed since our last read.
`QV4::ReferenceObject::readReference`, the base implementation for
read-backs, was modified to take into account the new "isDirty" flag.
When the flag is not set, we expect to already have the latest data, and
thus do not actually perform the read anymore.
Furthermore, the same implementation was modified to take care of
setting the `isDirty` flag to a correct state after a read is performed.
The connection to the NOTIFY signal is performed through the existing
`QQmlNotifier/Endpoint` infrastructure, which allows, between others, to
connect to signal emitted by a `QObject`, and should be more performant
than a naked connection.
Similarly, a BINDABLE is subscribed to by using its usual interface.
A new callback was added to be used by `ReferenceObject` to allow
setting the `isDirty` flag on the signal emission.
`ReferenceObject` will now store a `QQmlNotifierEndpoint` or a
`QPropertyNotifier`, that will take care of listening to upstream
changes and set the dirty flag as required.
A few bug-provening test cases where added to `tst_qqmllanguage` to test
that the number of unnecessary reads was indeed reduced.
Additional test cases were added to inspect certain aspects of the new
implementation to ensure that it works in certain common or edge cases.
The internal documentation for `ReferenceObject` was modified to mention
this new behavior.
Fixes: QTBUG-118847
Fixes: QTBUG-127322
Change-Id: Id62979ae4e03910e1165c293837e5d884727dddc
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ReferenceObject is currently the backbone of the the write-back
mechanism.
Add some basic documentation on its purpose and usages to try and reduce
the complexity of approaching some of the dependent code that deals with
write-backs (e.g Sequence, QQmlValueTypeWrapper, ...) and to simplify
approaching a review or performing work related to write-backs, which
currently still require some development.
Change-Id: I56f346c29c79313ebc6181ab87b9f7369115ad83
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
|
|
|
Every QQmlValueTypeWrapper is potentially a reference now. Since most
were already before, the overhead of checking the vtables at every step
was dubious at best.
Extract a common base class that handles the reading and writing of
object properties employed in both value type references and sequences.
Task-number: QTBUG-99766
Change-Id: Idf72d9a20a52366e5c2d0dcd4b3a18072c0ccc41
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|