Thunks/gen: Repack out-parameters on exit

To avoid performance traps, several conditions must hold for exit repacking
to apply:
* Argument must be a pointer
* The pointee type must have differing data layout between guest and host
* The pointee type must be non-const

Arguments that don't meet the first two conditions are safe *not* to repack
on exit, since they're either passed by copy or have consistent data layout.
The third condition is a heuristic: In principle, an API function could modify
data through nested pointers even if the argument pointer is const. However,
automatic repacking is not supported for such types anyway, so this is a safe
heuristic to use.
This commit is contained in:
Tony Wasserka 2024-01-12 14:47:10 +01:00
parent dc477c3bd7
commit 4cbaad298a

View File

@ -265,6 +265,20 @@ struct repack_wrapper {
}
}
~repack_wrapper() {
// TODO: Properly detect opaque types
if constexpr (requires(guest_layout<T> t, decltype(data) h) { t.get_pointer(); (bool)h; *data; }) {
if constexpr (!std::is_const_v<std::remove_pointer_t<T>>) { // Skip exit-repacking for const pointees
if (data) {
constexpr bool is_compatible = has_compatible_data_layout<T> && std::is_same_v<T, GuestT>;
if constexpr (!is_compatible && std::is_class_v<std::remove_pointer_t<T>>) {
*orig_arg.get_pointer() = to_guest(*data); // TODO: Only if annotated as out-parameter
}
}
}
}
}
operator PointeeT*() {
static_assert(sizeof(PointeeT) == sizeof(host_layout<PointeeT>));
static_assert(alignof(PointeeT) == alignof(host_layout<PointeeT>));