From c1f322dc42fe46a7a8c64db24a8d84b5532a24fd Mon Sep 17 00:00:00 2001 From: Thierry Treyer Date: Fri, 25 Aug 2023 09:57:49 -0700 Subject: [PATCH] Implement Container V2 for std::unordered_set --- .../std_unordered_set_custom_operator.toml | 9 ++- types/unordered_set_type.toml | 68 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/test/integration/std_unordered_set_custom_operator.toml b/test/integration/std_unordered_set_custom_operator.toml index 9df345a..3c01f6c 100644 --- a/test/integration/std_unordered_set_custom_operator.toml +++ b/test/integration/std_unordered_set_custom_operator.toml @@ -33,7 +33,6 @@ includes = ["unordered_set"] [cases] [cases.a] - oil_skip = "std::unordered_set is not implemented for treebuilder v2" # https://github.com/facebookexperimental/object-introspection/issues/302 param_types = ["const Foo&"] setup = ''' Foo foo; @@ -65,3 +64,11 @@ includes = ["unordered_set"] {"name":"m3", "staticSize":120, "dynamicSize":188, "length":7, "capacity":7, "elementStaticSize":12}, {"name":"m4", "staticSize":184, "dynamicSize":212, "length":9, "capacity":9, "elementStaticSize":12} ]}]''' + expect_json_v2 = '''[{ + "staticSize":480, + "members":[ + {"name":"m1", "staticSize":56, "exclusiveSize":220, "length":3, "capacity":3}, + {"name":"m2", "staticSize":120, "exclusiveSize":324, "length":5, "capacity":5}, + {"name":"m3", "staticSize":120, "exclusiveSize":364, "length":7, "capacity":7}, + {"name":"m4", "staticSize":184, "exclusiveSize":468, "length":9, "capacity":9} + ]}]''' diff --git a/types/unordered_set_type.toml b/types/unordered_set_type.toml index 380d0b8..9e88396 100644 --- a/types/unordered_set_type.toml +++ b/types/unordered_set_type.toml @@ -67,3 +67,71 @@ struct TypeHandler> { } }; """ + +traversal_func = """ +auto tail = returnArg + .write((uintptr_t)&container) + .write(container.bucket_count()) + .write(container.size()); + +for (const auto &it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); +} + +return tail.finish(); +""" + +[[codegen.processor]] +type = "types::st::VarInt" +func = """ +el.pointer = std::get(d.val).value; +""" + +[[codegen.processor]] +type = "types::st::VarInt" +func = """ +// Using the container's capacity to temporarily store the number of buckets +// TODO: Is there another way to pass a value across processors? +el.container_stats.emplace(result::Element::ContainerStats { + .capacity = std::get(d.val).value, +}); +""" + +[[codegen.processor]] +type = "types::st::List::type>" +func = """ +#ifdef __GLIBCXX__ +/* Use libstdc++ implementation __details to compute the size of Nodes and Buckets. + * + * See the source of : + * https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00536_source.html + */ +using OI_Hash_node = + std::__detail::_Hash_node::value>; + +using OI_bucket = std::__detail::_Hash_node_base; + +static constexpr size_t element_size = sizeof(OI_Hash_node); +static constexpr size_t bucket_size = sizeof(OI_bucket); +#else +static_assert(false && "No known element_size for sets. See types/set_type.toml"); +#endif + +auto list = std::get(d.val); +// Reading the bucket count that was stored in `capacity` by the processor above. +size_t bucket_count = el.container_stats->capacity; +el.exclusive_size += bucket_count * bucket_size; +el.exclusive_size += list.length * (element_size - sizeof(T0)); + +// Overwrite the bucket count stored in `capacity` with the actual container's values. +el.container_stats.emplace(result::Element::ContainerStats { + .capacity = list.length, + .length = list.length, +}); + +static constexpr auto childField = make_field("[]"); +for (size_t i = 0; i < list.length; i++) + ins.emplace(childField); +"""