diff --git a/oi/TreeBuilder.cpp b/oi/TreeBuilder.cpp index a99f3f8..7caf9bd 100644 --- a/oi/TreeBuilder.cpp +++ b/oi/TreeBuilder.cpp @@ -798,7 +798,12 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) { containerStats.length = containerStats.capacity = next(); break; case SMALL_VEC_TYPE: { - size_t maxInline = next(); + size_t requestedMaxInline = next(); + size_t maxInline = + requestedMaxInline == 0 + ? 0 + : std::max(sizeof(uintptr_t) / containerStats.elementStaticSize, + requestedMaxInline); containerStats.capacity = next(); containerStats.length = next(); contentsStoredInline = containerStats.capacity <= maxInline; diff --git a/test/integration/folly_shims.cpp b/test/integration/folly_shims.cpp index c2a82b4..b6985de 100644 --- a/test/integration/folly_shims.cpp +++ b/test/integration/folly_shims.cpp @@ -1,3 +1,4 @@ +#include #include namespace folly { @@ -18,5 +19,9 @@ void safe_assert_terminate(safe_assert_arg const* /*arg*/, ...) noexcept { abort(); } +void ScopeGuardImplBase::terminate() noexcept { + abort(); +} + } // namespace detail } // namespace folly diff --git a/test/integration/folly_small_vector.toml b/test/integration/folly_small_vector.toml new file mode 100644 index 0000000..89e3ae3 --- /dev/null +++ b/test/integration/folly_small_vector.toml @@ -0,0 +1,43 @@ +includes = ["folly/small_vector.h", "vector"] +[cases] + [cases.int_default_empty] + param_types = ["const folly::small_vector&"] + setup = "return {};" + expect_json = '[{"staticSize":16, "dynamicSize":0, "exclusiveSize":16, "length":0, "capacity":2, "elementStaticSize":4}]' + [cases.int_default_inlined] + param_types = ["const folly::small_vector&"] + setup = "return {{1,2}};" + expect_json = '[{"staticSize":16, "dynamicSize":0, "exclusiveSize":16, "length":2, "capacity":2, "elementStaticSize":4}]' + [cases.int_default_overflow] + param_types = ["const folly::small_vector&"] + setup = "return {{1,2,3,4}};" + expect_json = '[{"staticSize":16, "dynamicSize":24, "exclusiveSize":40, "length":4, "capacity":6, "elementStaticSize":4}]' + + [cases.vector_3_empty] + param_types = ["const folly::small_vector, 3>&"] + setup = "return {};" + expect_json = '[{"staticSize":80, "dynamicSize":0, "exclusiveSize":80, "length":0, "capacity":3, "elementStaticSize":24}]' + [cases.vector_3_inlined] + param_types = ["const folly::small_vector, 3>&"] + setup = "return {{ {1,2,3}, {4}, {5,6} }};" + expect_json = '''[ + {"staticSize":80, "dynamicSize":24, "length":3, "exclusiveSize":8, "capacity":3, "elementStaticSize":24, "members":[ + {"staticSize":24, "dynamicSize":12, "exclusiveSize":36, "length":3, "capacity":3, "elementStaticSize":4}, + {"staticSize":24, "dynamicSize":4, "exclusiveSize":28, "length":1, "capacity":1, "elementStaticSize":4}, + {"staticSize":24, "dynamicSize":8, "exclusiveSize":32, "length":2, "capacity":2, "elementStaticSize":4} + ]}]''' + [cases.vector_3_overflow] + param_types = ["const folly::small_vector, 3>&"] + setup = "return {{ {1,2,3}, {4}, {5,6}, {7} }};" + expect_json = '''[ + {"staticSize":80, "dynamicSize":148, "length":4, "exclusiveSize":104, "capacity":5, "elementStaticSize":24, "members":[ + {"staticSize":24, "dynamicSize":12, "exclusiveSize":36, "length":3, "capacity":3, "elementStaticSize":4}, + {"staticSize":24, "dynamicSize":4, "exclusiveSize":28, "length":1, "capacity":1, "elementStaticSize":4}, + {"staticSize":24, "dynamicSize":8, "exclusiveSize":32, "length":2, "capacity":2, "elementStaticSize":4}, + {"staticSize":24, "dynamicSize":4, "exclusiveSize":28, "length":1, "capacity":1, "elementStaticSize":4} + ]}]''' + + [cases.int_always_heap] + param_types = ["const folly::small_vector&"] + setup = "return {{1}};" + expect_json = '[{"staticSize":16, "dynamicSize":4, "exclusiveSize":20, "length":1, "capacity":1, "elementStaticSize":4}]' diff --git a/test/integration/folly_sorted_vector_map.toml b/test/integration/folly_sorted_vector_map.toml new file mode 100644 index 0000000..2db67ab --- /dev/null +++ b/test/integration/folly_sorted_vector_map.toml @@ -0,0 +1,21 @@ +includes = ["folly/sorted_vector_types.h", "vector"] +[cases] + [cases.int_int_empty] + param_types = ["const folly::sorted_vector_map&"] + setup = "return {};" + expect_json = '[{"staticSize":24, "dynamicSize":0, "exclusiveSize":24, "length":0, "capacity":0, "elementStaticSize":8}]' + [cases.int_int_some] + param_types = ["const folly::sorted_vector_map&"] + setup = "return {{ {1,2}, {3,4} }};" + expect_json = '[{"staticSize":24, "dynamicSize":16, "exclusiveSize":40, "length":2, "capacity":2, "elementStaticSize":8}]' + + [cases.int_vector_empty] + skip = "Wrong results" # https://github.com/facebookexperimental/object-introspection/issues/258 + param_types = ["const folly::sorted_vector_map>&"] + setup = "return {};" + expect_json = '[{"staticSize":24, "dynamicSize":0, "exclusiveSize":24, "length":0, "capacity":0, "elementStaticSize":32}]' + [cases.int_vector_some] + skip = "Wrong results" # https://github.com/facebookexperimental/object-introspection/issues/258 + param_types = ["const folly::sorted_vector_map>&"] + setup = "return {{ {1,{2,3}}, {4,{5,6,7}} }};" + #expect_json = "TODO" diff --git a/types/map_seq_type.toml b/types/map_seq_type.toml index 9d0273a..efa107c 100644 --- a/types/map_seq_type.toml +++ b/types/map_seq_type.toml @@ -2,6 +2,7 @@ type_name = "folly::sorted_vector_map" ctype = "MAP_SEQ_TYPE" header = "folly/sorted_vector_types.h" +stub_template_params = [2,3] # Old: typeName = "folly::sorted_vector_map<" @@ -34,3 +35,34 @@ void getSizeType(const %1% +struct TypeHandler> { + using type = types::st::Pair, + types::st::Pair, + types::st::List::type, + typename TypeHandler::type + >>>>; + + static types::st::Unit getSizeType( + const %1%& container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write((uintptr_t)&container) + .write(container.capacity()) + .write(container.size()); + + for (const auto& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.second, ret.delegate([&it](auto ret) { + return OIInternal::getSizeType(it.first, ret); + })); + }); + } + + return tail.finish(); + } +}; +""" diff --git a/types/small_vec_type.toml b/types/small_vec_type.toml index 22e8275..20a0288 100644 --- a/types/small_vec_type.toml +++ b/types/small_vec_type.toml @@ -2,6 +2,7 @@ type_name = "folly::small_vector" ctype = "SMALL_VEC_TYPE" header = "folly/small_vector.h" +stub_template_params = [2] # Old: typeName = "folly::small_vector<" @@ -20,6 +21,17 @@ template void getSizeType(const %1% &container, size_t& returnArg) { SAVE_SIZE(sizeof(%1%)); + + bool dataInlined = ((uintptr_t)container.data() >= (uintptr_t)&container) && + ((uintptr_t)container.data() < (uintptr_t)(&container + sizeof(%1%))); + if (dataInlined) { + // Don't double count inlined elements + SAVE_SIZE(-(container.size() * sizeof(V))); + } else { + // Account for wasted space in the buffer + SAVE_SIZE((container.capacity() - container.size()) * sizeof(V)); + } + SAVE_DATA((uintptr_t)(N)); SAVE_DATA((uintptr_t)container.capacity()); SAVE_DATA((uintptr_t)container.size()); @@ -29,3 +41,29 @@ void getSizeType(const %1% &container, size_t& returnArg) } } """ +handler = """ +template +struct TypeHandler> { + using type = types::st::Pair< + DB, types::st::VarInt, + types::st::Pair< + DB, types::st::VarInt, + types::st::List::type>>>; + + static types::st::Unit getSizeType( + const %1% & container, + typename TypeHandler>::type returnArg) { + auto tail = returnArg.write(N0) + .write(container.capacity()) + .write(container.size()); + + for (auto& it : container) { + tail = tail.delegate([&it](auto ret) { + return OIInternal::getSizeType(it, ret); + }); + } + + return tail.finish(); + } +}; +"""