Skip to content

WIP: Rewrite arguments cache using C++ inheritance

Marco Trevisan requested to merge 3v1n0/gjs:cpp-dynamic-arg-cache into master

While I think this is pretty much what I wanted to do, I marked as WIP as it mostly dependent on !496 (merged), !514 (merged) and !515 (even though, the changes depending on that ones could be separated, in case).

By the way, the Argument cache (included with !48 (merged)) it's quite nice however, being written over 7 years ago wasn't really taking advantage of C++ at all.

Now, most of things that it wanted to achieve are possible by just using actual virtual functions and structs in C++ with the help with some static fun, but also we can go a bit further by using different GjsArgument implementations depending on the type we want to marshall, also taking advantage of C++'s multi-inheritance (used to act like we have interfaces).

So, currently for each function we have an argument cache that that for each function initialize an array of equal structures that might contain information that aren't needed for the type we're handling, thus some waste of space. Then we use other structures to handle the marshallers.

C++ allows us however to have virtual functions though (which eventually take the same space that our marshallers pointer would), and also supports multi-inheritance and using those two things we can make the argument cache a bit smarter and use more C++ code.

As per this, added a GjsArgsCache struct that we use inside Function to manage the arguments without having to care about the internal implementation at that level.

Then we define a generic virtual GjsArgument struct and we implement internally using different types depending on the marshalling action we want to do.

As per this, we can convert most of our functions to c++ functions quite easily, and leave the memory management to the smart pointers.

This implies that in general we can reduce the space used to store the cache for each function arguments, with few exceptions, but this should be generally more convenient for the most used types, as per the newly added marshallers that take less space and per the fact we don't store anymore infos for void functions (we could also do it for skipped parameters, but would need a further pass).

Here's the new `GjsArgument` sizes
Size of BaseInfo 16
Size of BasicArrayIn 32
Size of BasicArrayOut 32
Size of BasicCArray 4
Size of BasicCFixedSizeArrayIn 32
Size of BasicCFixedSizeArrayOut 32
Size of BasicCZeroTeminatedArrayIn 32
Size of BasicCZeroTeminatedArrayOut 32
Size of BasicExplicitCArrayIn 32
Size of BasicExplicitCArrayInOut 32
Size of BasicExplicitCArrayOut 32
Size of BasicGHashIn 32
Size of BasicGHashOut 32
Size of BasicGListIn 32
Size of BasicGListOut 32
Size of BasicPtrArrayIn 32
Size of BasicPtrArrayOut 32
Size of BasicType 4
Size of BasicTypeIn 24
Size of BasicTypeInContainer 32
Size of BasicTypeOut 24
Size of BasicTypeOutContainer 32
Size of BasicTypeTransferableOut 32
Size of BooleanIn 24
Size of BoxedIn 40
Size of BoxedInTransferNone 40
Size of ByteArrayIn 24
Size of ByteArrayOut 24
Size of CArrayIn 104
Size of CArrayInOut 104
Size of CArrayOut 104
Size of Callback 24
Size of CallbackIn 48
Size of CallerAllocates 8
Size of CallerAllocatesOut 112
Size of Enum 12
Size of EnumIn 32
Size of ErrorIn 32
Size of ExplicitArray 1
Size of ExplicitArrayBase 32
Size of ExplicitArrayIn 32
Size of ExplicitArrayInOut 32
Size of ExplicitArrayOut 32
Size of Fallback 80
Size of FallbackIn 112
Size of FallbackInOut 112
Size of FallbackInterfaceIn 56
Size of FallbackOut 104
Size of FilenameIn 24
Size of FilenameInTransferNone 24
Size of FixedSizeArray 4
Size of Flags 4
Size of FlagsIn 24
Size of ForeignStructIn 56
Size of ForeignStructInstanceIn 56
Size of FundamentalIn 40
Size of GBytesIn 40
Size of GBytesInTransferNone 40
Size of GClosureIn 40
Size of GClosureInTransferNone 40
Size of GHash 4
Size of GList 1
Size of GTypeIn 24
Size of GTypeStructInstanceIn 24
Size of GValueIn 40
Size of GValueInTransferNone 40
Size of GdkAtomIn 56
Size of Generic 24
Size of GenericIn 24
Size of GenericInOut 24
Size of GenericOut 24
Size of GenericReturn 104
Size of Instance 24
Size of InterfaceIn 40
Size of NullIn 24
Size of Nullable 1
Size of NullableIn 24
Size of NumericIn 24
Size of ObjectIn 40
Size of ParamInstanceIn 24
Size of Positioned 1
Size of RegisteredIn 40
Size of RegisteredInterface 24
Size of RegisteredInterfaceIn 56
Size of RegisteredType 16
Size of ReturnArray 32
Size of SimpleOut 24
Size of SkipAll 24
Size of String 1
Size of StringIn 24
Size of StringInTransferNone 24
Size of Transferable 4
Size of TypeInfo 72
Size of UnicharIn 24
Size of UnionIn 40
Size of UnregisteredBoxedIn 56

Finally... I was thinking whether would be the case to use the garbage collector to also cleanup the functions cache, so that a function get's renewed each time that the gc passes, but if not used for two cycles, we just drop its cache.

Edited by Marco Trevisan

Merge request reports