QJniObject: use ctor delegation instead of construct+assign

The old code used unintialized construction followed by (move)
assignment to construct a QJniObject that requires a LocalFrame
object. That is two constructors and therefore one more than we need
(and need to destroy in inline code again).

Everything can be solved with another level of indirection.™

Since the LocalFrame needs to remain alive for the duration of
argument evaluation, the usual comma operator trick won't work. But we
can add a private helper ctor that takes the LocalFrame as an
additional argument to inject the object with the correct lifetime
into the ctor delegation chain.

Put the new argument in the front, to avoid clashes with the primary
contructor's trailing universal references, which might be a better
match than the new overload had we added the argument at the end. The
hope is that the compiler will avoid the ensuing register shuffling by
inlining the outer two constructor calls.

This brings the number of QJniObjects constructed down to one, as it
should be. We might also be able to remove the Uninitialized ctor
again.

Found in API-review.

Amends 62cb5589b3.

Pick-to: 6.7
Change-Id: I326187e54fd0705a1bbedb2d51d94a46b108a3c8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Marc Mutz 2024-02-29 14:48:01 +01:00
parent 41854cfaac
commit ddaf764282
1 changed files with 9 additions and 4 deletions

View File

@ -71,12 +71,17 @@ public:
#endif
>
explicit QJniObject(const char *className, Args &&...args)
: QJniObject(Qt::Uninitialized)
: QJniObject(LocalFrame<Args...>{}, className, std::forward<Args>(args)...)
{
LocalFrame<Args...> localFrame;
*this = QJniObject(className, QtJniTypes::constructorSignature<Args...>().data(),
localFrame.convertToJni(std::forward<Args>(args))...);
}
private:
template<typename ...Args>
explicit QJniObject(LocalFrame<Args...> localFrame, const char *className, Args &&...args)
: QJniObject(className, QtJniTypes::constructorSignature<Args...>().data(),
localFrame.convertToJni(std::forward<Args>(args))...)
{
}
public:
explicit QJniObject(jclass clazz);
explicit QJniObject(jclass clazz, const char *signature, ...);
template<typename ...Args