re2 1.24.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/LICENSE +15 -20
  2. package/README.md +63 -4
  3. package/binding.gyp +1 -2
  4. package/lib/addon.cc +9 -5
  5. package/lib/exec.cc +4 -4
  6. package/lib/match.cc +4 -4
  7. package/lib/new.cc +6 -6
  8. package/lib/pattern.cc +148 -1
  9. package/lib/replace.cc +5 -4
  10. package/lib/search.cc +1 -1
  11. package/lib/set.cc +85 -10
  12. package/lib/test.cc +1 -1
  13. package/lib/unicode_properties.h +15840 -0
  14. package/lib/wrapped_re2.h +40 -4
  15. package/lib/wrapped_re2_set.h +3 -1
  16. package/llms-full.txt +497 -0
  17. package/llms.txt +135 -0
  18. package/package.json +19 -11
  19. package/re2.d.ts +2 -0
  20. package/re2.js +1 -0
  21. package/vendor/abseil-cpp/CMake/AbseilDll.cmake +87 -74
  22. package/vendor/abseil-cpp/CMakeLists.txt +3 -3
  23. package/vendor/abseil-cpp/FAQ.md +130 -79
  24. package/vendor/abseil-cpp/MODULE.bazel +6 -7
  25. package/vendor/abseil-cpp/absl/BUILD.bazel +6 -0
  26. package/vendor/abseil-cpp/absl/algorithm/BUILD.bazel +4 -0
  27. package/vendor/abseil-cpp/absl/algorithm/CMakeLists.txt +4 -0
  28. package/vendor/abseil-cpp/absl/algorithm/algorithm.h +34 -2
  29. package/vendor/abseil-cpp/absl/algorithm/container.h +164 -17
  30. package/vendor/abseil-cpp/absl/algorithm/container_test.cc +390 -13
  31. package/vendor/abseil-cpp/absl/base/BUILD.bazel +53 -6
  32. package/vendor/abseil-cpp/absl/base/CMakeLists.txt +28 -4
  33. package/vendor/abseil-cpp/absl/base/attributes.h +61 -42
  34. package/vendor/abseil-cpp/absl/base/call_once.h +1 -0
  35. package/vendor/abseil-cpp/absl/base/casts.h +8 -1
  36. package/vendor/abseil-cpp/absl/base/casts_test.cc +3 -6
  37. package/vendor/abseil-cpp/absl/base/config.h +53 -9
  38. package/vendor/abseil-cpp/absl/base/exception_safety_testing_test.cc +9 -9
  39. package/vendor/abseil-cpp/absl/base/fast_type_id.h +30 -2
  40. package/vendor/abseil-cpp/absl/base/fast_type_id_test.cc +3 -0
  41. package/vendor/abseil-cpp/absl/base/internal/exception_safety_testing.h +15 -12
  42. package/vendor/abseil-cpp/absl/base/internal/hardening.h +136 -0
  43. package/vendor/abseil-cpp/absl/base/internal/hardening_test.cc +168 -0
  44. package/vendor/abseil-cpp/absl/base/internal/iterator_traits.h +2 -2
  45. package/vendor/abseil-cpp/absl/base/internal/low_level_alloc.cc +6 -0
  46. package/vendor/abseil-cpp/absl/base/internal/low_level_scheduling.h +77 -15
  47. package/vendor/abseil-cpp/absl/base/internal/sysinfo.cc +1 -2
  48. package/vendor/abseil-cpp/absl/base/internal/thread_identity.h +52 -0
  49. package/vendor/abseil-cpp/absl/base/internal/unscaledcycleclock.h +5 -0
  50. package/vendor/abseil-cpp/absl/base/macros.h +36 -20
  51. package/vendor/abseil-cpp/absl/base/nullability.h +4 -3
  52. package/vendor/abseil-cpp/absl/base/optimization.h +3 -2
  53. package/vendor/abseil-cpp/absl/base/optimization_test.cc +4 -3
  54. package/vendor/abseil-cpp/absl/base/options.h +55 -1
  55. package/vendor/abseil-cpp/absl/base/policy_checks.h +5 -5
  56. package/vendor/abseil-cpp/absl/base/{internal/throw_delegate.cc → throw_delegate.cc} +9 -7
  57. package/vendor/abseil-cpp/absl/base/{internal/throw_delegate.h → throw_delegate.h} +4 -14
  58. package/vendor/abseil-cpp/absl/base/throw_delegate_test.cc +19 -28
  59. package/vendor/abseil-cpp/absl/cleanup/BUILD.bazel +2 -0
  60. package/vendor/abseil-cpp/absl/cleanup/CMakeLists.txt +2 -0
  61. package/vendor/abseil-cpp/absl/cleanup/cleanup.h +3 -2
  62. package/vendor/abseil-cpp/absl/cleanup/internal/cleanup.h +3 -2
  63. package/vendor/abseil-cpp/absl/container/BUILD.bazel +19 -7
  64. package/vendor/abseil-cpp/absl/container/CMakeLists.txt +6 -5
  65. package/vendor/abseil-cpp/absl/container/btree_benchmark.cc +3 -5
  66. package/vendor/abseil-cpp/absl/container/btree_set.h +5 -5
  67. package/vendor/abseil-cpp/absl/container/btree_test.cc +11 -14
  68. package/vendor/abseil-cpp/absl/container/chunked_queue.h +8 -6
  69. package/vendor/abseil-cpp/absl/container/chunked_queue_test.cc +5 -5
  70. package/vendor/abseil-cpp/absl/container/fixed_array.h +14 -13
  71. package/vendor/abseil-cpp/absl/container/fixed_array_test.cc +3 -3
  72. package/vendor/abseil-cpp/absl/container/flat_hash_map.h +18 -6
  73. package/vendor/abseil-cpp/absl/container/flat_hash_map_test.cc +34 -1
  74. package/vendor/abseil-cpp/absl/container/flat_hash_set.h +21 -7
  75. package/vendor/abseil-cpp/absl/container/flat_hash_set_test.cc +39 -7
  76. package/vendor/abseil-cpp/absl/container/inlined_vector.h +29 -29
  77. package/vendor/abseil-cpp/absl/container/inlined_vector_test.cc +2 -2
  78. package/vendor/abseil-cpp/absl/container/internal/btree.h +32 -24
  79. package/vendor/abseil-cpp/absl/container/internal/btree_container.h +16 -17
  80. package/vendor/abseil-cpp/absl/container/internal/common.h +6 -5
  81. package/vendor/abseil-cpp/absl/container/internal/common_policy_traits.h +1 -1
  82. package/vendor/abseil-cpp/absl/container/internal/compressed_tuple.h +16 -16
  83. package/vendor/abseil-cpp/absl/container/internal/compressed_tuple_test.cc +13 -13
  84. package/vendor/abseil-cpp/absl/container/internal/container_memory.h +41 -31
  85. package/vendor/abseil-cpp/absl/container/internal/hash_function_defaults.h +2 -2
  86. package/vendor/abseil-cpp/absl/container/internal/hash_generator_testing.h +4 -4
  87. package/vendor/abseil-cpp/absl/container/internal/hash_policy_traits.h +3 -3
  88. package/vendor/abseil-cpp/absl/container/internal/hashtable_control_bytes.h +27 -19
  89. package/vendor/abseil-cpp/absl/container/internal/hashtablez_sampler.cc +2 -2
  90. package/vendor/abseil-cpp/absl/container/internal/hashtablez_sampler.h +0 -17
  91. package/vendor/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc +12 -30
  92. package/vendor/abseil-cpp/absl/container/internal/inlined_vector.h +28 -28
  93. package/vendor/abseil-cpp/absl/container/internal/layout.h +13 -13
  94. package/vendor/abseil-cpp/absl/container/internal/layout_test.cc +3 -2
  95. package/vendor/abseil-cpp/absl/container/internal/raw_hash_map.h +60 -62
  96. package/vendor/abseil-cpp/absl/container/internal/raw_hash_set.cc +59 -39
  97. package/vendor/abseil-cpp/absl/container/internal/raw_hash_set.h +619 -326
  98. package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc +25 -2
  99. package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc +4 -4
  100. package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_test.cc +575 -159
  101. package/vendor/abseil-cpp/absl/container/linked_hash_map.h +2 -2
  102. package/vendor/abseil-cpp/absl/container/node_hash_map.h +27 -15
  103. package/vendor/abseil-cpp/absl/container/node_hash_map_test.cc +34 -0
  104. package/vendor/abseil-cpp/absl/container/node_hash_set.h +25 -11
  105. package/vendor/abseil-cpp/absl/container/node_hash_set_test.cc +39 -7
  106. package/vendor/abseil-cpp/absl/container/sample_element_size_test.cc +7 -4
  107. package/vendor/abseil-cpp/absl/crc/BUILD.bazel +0 -1
  108. package/vendor/abseil-cpp/absl/crc/CMakeLists.txt +2 -3
  109. package/vendor/abseil-cpp/absl/crc/crc32c_benchmark.cc +2 -1
  110. package/vendor/abseil-cpp/absl/crc/internal/cpu_detect.cc +6 -6
  111. package/vendor/abseil-cpp/absl/crc/internal/crc.cc +4 -6
  112. package/vendor/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h +41 -0
  113. package/vendor/abseil-cpp/absl/crc/internal/crc_internal.h +0 -16
  114. package/vendor/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc +143 -81
  115. package/vendor/abseil-cpp/absl/debugging/BUILD.bazel +9 -31
  116. package/vendor/abseil-cpp/absl/debugging/CMakeLists.txt +3 -33
  117. package/vendor/abseil-cpp/absl/debugging/internal/demangle_rust.h +8 -0
  118. package/vendor/abseil-cpp/absl/debugging/internal/demangle_test.cc +2 -1
  119. package/vendor/abseil-cpp/absl/debugging/internal/examine_stack.cc +12 -2
  120. package/vendor/abseil-cpp/absl/debugging/internal/examine_stack.h +2 -3
  121. package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +11 -0
  122. package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc +13 -4
  123. package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc +14 -7
  124. package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc +4 -0
  125. package/vendor/abseil-cpp/absl/debugging/internal/symbolize.h +46 -36
  126. package/vendor/abseil-cpp/absl/debugging/stacktrace.cc +18 -58
  127. package/vendor/abseil-cpp/absl/debugging/stacktrace.h +5 -48
  128. package/vendor/abseil-cpp/absl/debugging/stacktrace_test.cc +10 -124
  129. package/vendor/abseil-cpp/absl/debugging/symbolize.cc +20 -2
  130. package/vendor/abseil-cpp/absl/debugging/symbolize_elf.inc +58 -106
  131. package/vendor/abseil-cpp/absl/debugging/symbolize_test.cc +37 -36
  132. package/vendor/abseil-cpp/absl/debugging/symbolize_unimplemented.inc +4 -4
  133. package/vendor/abseil-cpp/absl/flags/BUILD.bazel +6 -3
  134. package/vendor/abseil-cpp/absl/flags/CMakeLists.txt +1 -1
  135. package/vendor/abseil-cpp/absl/flags/commandlineflag.h +8 -6
  136. package/vendor/abseil-cpp/absl/flags/commandlineflag_test.cc +1 -1
  137. package/vendor/abseil-cpp/absl/flags/flag_benchmark.cc +5 -5
  138. package/vendor/abseil-cpp/absl/flags/flag_test.cc +30 -30
  139. package/vendor/abseil-cpp/absl/flags/internal/flag.cc +4 -4
  140. package/vendor/abseil-cpp/absl/flags/internal/flag.h +6 -6
  141. package/vendor/abseil-cpp/absl/flags/marshalling.h +2 -28
  142. package/vendor/abseil-cpp/absl/flags/marshalling_test.cc +12 -11
  143. package/vendor/abseil-cpp/absl/flags/reflection_test.cc +1 -1
  144. package/vendor/abseil-cpp/absl/functional/BUILD.bazel +26 -1
  145. package/vendor/abseil-cpp/absl/functional/CMakeLists.txt +29 -1
  146. package/vendor/abseil-cpp/absl/functional/any_invocable.h +13 -14
  147. package/vendor/abseil-cpp/absl/functional/any_invocable_test.cc +46 -47
  148. package/vendor/abseil-cpp/absl/functional/bind_back.h +79 -0
  149. package/vendor/abseil-cpp/absl/functional/bind_back_test.cc +237 -0
  150. package/vendor/abseil-cpp/absl/functional/bind_front.h +7 -1
  151. package/vendor/abseil-cpp/absl/functional/bind_front_test.cc +4 -4
  152. package/vendor/abseil-cpp/absl/functional/function_ref_test.cc +2 -2
  153. package/vendor/abseil-cpp/absl/functional/internal/any_invocable.h +28 -28
  154. package/vendor/abseil-cpp/absl/functional/internal/back_binder.h +95 -0
  155. package/vendor/abseil-cpp/absl/functional/internal/front_binder.h +4 -4
  156. package/vendor/abseil-cpp/absl/functional/internal/function_ref.h +2 -2
  157. package/vendor/abseil-cpp/absl/functional/overload_test.cc +13 -13
  158. package/vendor/abseil-cpp/absl/hash/BUILD.bazel +1 -2
  159. package/vendor/abseil-cpp/absl/hash/CMakeLists.txt +1 -2
  160. package/vendor/abseil-cpp/absl/hash/hash.h +1 -1
  161. package/vendor/abseil-cpp/absl/hash/hash_test.cc +14 -20
  162. package/vendor/abseil-cpp/absl/hash/hash_testing.h +11 -9
  163. package/vendor/abseil-cpp/absl/hash/internal/city.cc +39 -51
  164. package/vendor/abseil-cpp/absl/hash/internal/hash.cc +165 -47
  165. package/vendor/abseil-cpp/absl/hash/internal/hash.h +86 -27
  166. package/vendor/abseil-cpp/absl/hash/internal/low_level_hash_test.cc +36 -1
  167. package/vendor/abseil-cpp/absl/hash/internal/spy_hash_state.h +8 -5
  168. package/vendor/abseil-cpp/absl/log/BUILD.bazel +5 -2
  169. package/vendor/abseil-cpp/absl/log/CMakeLists.txt +5 -3
  170. package/vendor/abseil-cpp/absl/log/absl_vlog_is_on.h +0 -2
  171. package/vendor/abseil-cpp/absl/log/internal/BUILD.bazel +15 -1
  172. package/vendor/abseil-cpp/absl/log/internal/log_message.cc +5 -4
  173. package/vendor/abseil-cpp/absl/log/internal/log_message.h +14 -0
  174. package/vendor/abseil-cpp/absl/log/internal/nullstream.h +1 -1
  175. package/vendor/abseil-cpp/absl/log/internal/proto.cc +13 -0
  176. package/vendor/abseil-cpp/absl/log/internal/structured_proto.cc +5 -5
  177. package/vendor/abseil-cpp/absl/log/internal/structured_proto.h +6 -5
  178. package/vendor/abseil-cpp/absl/log/internal/structured_proto_test.cc +3 -3
  179. package/vendor/abseil-cpp/absl/log/internal/vlog_config.cc +2 -2
  180. package/vendor/abseil-cpp/absl/log/internal/vlog_config_benchmark.cc +3 -3
  181. package/vendor/abseil-cpp/absl/log/log_format_test.cc +19 -2
  182. package/vendor/abseil-cpp/absl/log/log_modifier_methods_test.cc +18 -0
  183. package/vendor/abseil-cpp/absl/log/log_streamer.h +29 -2
  184. package/vendor/abseil-cpp/absl/log/log_streamer_test.cc +18 -0
  185. package/vendor/abseil-cpp/absl/log/scoped_mock_log_test.cc +1 -1
  186. package/vendor/abseil-cpp/absl/log/vlog_is_on.h +0 -2
  187. package/vendor/abseil-cpp/absl/log/vlog_is_on_test.cc +6 -5
  188. package/vendor/abseil-cpp/absl/memory/memory.h +55 -5
  189. package/vendor/abseil-cpp/absl/memory/memory_test.cc +55 -1
  190. package/vendor/abseil-cpp/absl/meta/BUILD.bazel +2 -0
  191. package/vendor/abseil-cpp/absl/meta/internal/requires.h +1 -1
  192. package/vendor/abseil-cpp/absl/meta/type_traits.h +119 -55
  193. package/vendor/abseil-cpp/absl/meta/type_traits_test.cc +7 -7
  194. package/vendor/abseil-cpp/absl/numeric/int128_test.cc +6 -6
  195. package/vendor/abseil-cpp/absl/profiling/BUILD.bazel +3 -1
  196. package/vendor/abseil-cpp/absl/profiling/hashtable.cc +0 -4
  197. package/vendor/abseil-cpp/absl/profiling/internal/profile_builder.cc +32 -33
  198. package/vendor/abseil-cpp/absl/profiling/internal/profile_builder.h +25 -2
  199. package/vendor/abseil-cpp/absl/profiling/internal/sample_recorder_test.cc +8 -5
  200. package/vendor/abseil-cpp/absl/random/BUILD.bazel +13 -1
  201. package/vendor/abseil-cpp/absl/random/CMakeLists.txt +23 -2
  202. package/vendor/abseil-cpp/absl/random/benchmarks.cc +1 -1
  203. package/vendor/abseil-cpp/absl/random/beta_distribution.h +2 -2
  204. package/vendor/abseil-cpp/absl/random/bit_gen_ref.h +26 -53
  205. package/vendor/abseil-cpp/absl/random/bit_gen_ref_test.cc +43 -0
  206. package/vendor/abseil-cpp/absl/random/discrete_distribution.h +1 -1
  207. package/vendor/abseil-cpp/absl/random/distributions.h +17 -17
  208. package/vendor/abseil-cpp/absl/random/distributions_test.cc +4 -4
  209. package/vendor/abseil-cpp/absl/random/exponential_distribution.h +1 -1
  210. package/vendor/abseil-cpp/absl/random/internal/BUILD.bazel +4 -2
  211. package/vendor/abseil-cpp/absl/random/internal/distribution_caller.h +8 -21
  212. package/vendor/abseil-cpp/absl/random/internal/fast_uniform_bits.h +1 -1
  213. package/vendor/abseil-cpp/absl/random/internal/generate_real.h +1 -1
  214. package/vendor/abseil-cpp/absl/random/internal/iostream_state_saver.h +2 -2
  215. package/vendor/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc +3 -2
  216. package/vendor/abseil-cpp/absl/random/internal/mock_helpers.h +14 -40
  217. package/vendor/abseil-cpp/absl/random/internal/nonsecure_base.h +2 -2
  218. package/vendor/abseil-cpp/absl/random/internal/nonsecure_base_test.cc +2 -2
  219. package/vendor/abseil-cpp/absl/random/internal/pcg_engine.h +6 -6
  220. package/vendor/abseil-cpp/absl/random/internal/pcg_engine_test.cc +3 -2
  221. package/vendor/abseil-cpp/absl/random/internal/randen_detect.cc +6 -6
  222. package/vendor/abseil-cpp/absl/random/internal/randen_engine.h +2 -2
  223. package/vendor/abseil-cpp/absl/random/internal/randen_engine_test.cc +3 -2
  224. package/vendor/abseil-cpp/absl/random/internal/randen_test.cc +3 -2
  225. package/vendor/abseil-cpp/absl/random/internal/salted_seed_seq.h +6 -5
  226. package/vendor/abseil-cpp/absl/random/internal/seed_material.cc +4 -4
  227. package/vendor/abseil-cpp/absl/random/internal/seed_material.h +2 -1
  228. package/vendor/abseil-cpp/absl/random/internal/traits.h +21 -0
  229. package/vendor/abseil-cpp/absl/random/internal/traits_test.cc +5 -0
  230. package/vendor/abseil-cpp/absl/random/internal/uniform_helper.h +23 -23
  231. package/vendor/abseil-cpp/absl/random/internal/uniform_helper_test.cc +2 -1
  232. package/vendor/abseil-cpp/absl/random/mocking_access.h +74 -0
  233. package/vendor/abseil-cpp/absl/random/mocking_bit_gen.h +9 -19
  234. package/vendor/abseil-cpp/absl/random/uniform_real_distribution.h +1 -1
  235. package/vendor/abseil-cpp/absl/status/BUILD.bazel +81 -0
  236. package/vendor/abseil-cpp/absl/status/CMakeLists.txt +91 -0
  237. package/vendor/abseil-cpp/absl/status/internal/status_internal.cc +63 -18
  238. package/vendor/abseil-cpp/absl/status/internal/status_internal.h +26 -2
  239. package/vendor/abseil-cpp/absl/status/internal/status_matchers.h +22 -8
  240. package/vendor/abseil-cpp/absl/status/internal/statusor_internal.h +43 -43
  241. package/vendor/abseil-cpp/absl/status/status.cc +62 -70
  242. package/vendor/abseil-cpp/absl/status/status.h +249 -23
  243. package/vendor/abseil-cpp/absl/status/status_benchmark.cc +12 -0
  244. package/vendor/abseil-cpp/absl/status/status_builder.cc +196 -0
  245. package/vendor/abseil-cpp/absl/status/status_builder.h +978 -0
  246. package/vendor/abseil-cpp/absl/status/status_builder_test.cc +380 -0
  247. package/vendor/abseil-cpp/absl/status/status_macros.h +484 -0
  248. package/vendor/abseil-cpp/absl/status/status_macros_test.cc +634 -0
  249. package/vendor/abseil-cpp/absl/status/status_matchers.h +2 -1
  250. package/vendor/abseil-cpp/absl/status/status_matchers_test.cc +3 -4
  251. package/vendor/abseil-cpp/absl/status/status_payload_printer.h +3 -2
  252. package/vendor/abseil-cpp/absl/status/status_test.cc +443 -13
  253. package/vendor/abseil-cpp/absl/status/statusor.h +69 -36
  254. package/vendor/abseil-cpp/absl/status/statusor_test.cc +132 -35
  255. package/vendor/abseil-cpp/absl/strings/BUILD.bazel +42 -7
  256. package/vendor/abseil-cpp/absl/strings/CMakeLists.txt +33 -4
  257. package/vendor/abseil-cpp/absl/strings/ascii.h +1 -2
  258. package/vendor/abseil-cpp/absl/strings/atod_manual_test.cc +5 -5
  259. package/vendor/abseil-cpp/absl/strings/cord.cc +26 -7
  260. package/vendor/abseil-cpp/absl/strings/cord.h +23 -13
  261. package/vendor/abseil-cpp/absl/strings/cord_buffer.h +4 -2
  262. package/vendor/abseil-cpp/absl/strings/cord_test.cc +85 -9
  263. package/vendor/abseil-cpp/absl/strings/escaping.cc +183 -35
  264. package/vendor/abseil-cpp/absl/strings/escaping.h +12 -2
  265. package/vendor/abseil-cpp/absl/strings/escaping_benchmark.cc +1 -3
  266. package/vendor/abseil-cpp/absl/strings/escaping_test.cc +22 -18
  267. package/vendor/abseil-cpp/absl/strings/has_absl_stringify_test.cc +2 -2
  268. package/vendor/abseil-cpp/absl/strings/has_ostream_operator_test.cc +2 -2
  269. package/vendor/abseil-cpp/absl/strings/internal/append_and_overwrite.h +10 -10
  270. package/vendor/abseil-cpp/absl/strings/internal/cordz_sample_token_test.cc +1 -1
  271. package/vendor/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc +6 -0
  272. package/vendor/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.h +1 -0
  273. package/vendor/abseil-cpp/absl/strings/internal/escaping.cc +0 -141
  274. package/vendor/abseil-cpp/absl/strings/internal/escaping.h +2 -26
  275. package/vendor/abseil-cpp/absl/strings/internal/generic_printer_internal.h +23 -2
  276. package/vendor/abseil-cpp/absl/strings/internal/generic_printer_test.cc +6 -2
  277. package/vendor/abseil-cpp/absl/strings/internal/resize_uninitialized.h +31 -24
  278. package/vendor/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc +16 -41
  279. package/vendor/abseil-cpp/absl/strings/internal/stl_type_traits.h +39 -39
  280. package/vendor/abseil-cpp/absl/strings/internal/str_format/arg.h +14 -22
  281. package/vendor/abseil-cpp/absl/strings/internal/str_format/bind.h +2 -2
  282. package/vendor/abseil-cpp/absl/strings/internal/str_format/convert_test.cc +12 -20
  283. package/vendor/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc +510 -307
  284. package/vendor/abseil-cpp/absl/strings/internal/str_join_internal.h +0 -1
  285. package/vendor/abseil-cpp/absl/strings/internal/str_split_internal.h +9 -10
  286. package/vendor/abseil-cpp/absl/strings/internal/string_constant_test.cc +6 -5
  287. package/vendor/abseil-cpp/absl/strings/internal/stringify_sink.h +12 -0
  288. package/vendor/abseil-cpp/absl/strings/internal/stringify_stream.h +119 -0
  289. package/vendor/abseil-cpp/absl/strings/internal/stringify_stream_test.cc +111 -0
  290. package/vendor/abseil-cpp/absl/strings/numbers.cc +406 -0
  291. package/vendor/abseil-cpp/absl/strings/numbers.h +4 -0
  292. package/vendor/abseil-cpp/absl/strings/numbers_test.cc +33 -0
  293. package/vendor/abseil-cpp/absl/strings/resize_and_overwrite.h +10 -6
  294. package/vendor/abseil-cpp/absl/strings/str_cat.h +36 -1
  295. package/vendor/abseil-cpp/absl/strings/str_cat_benchmark.cc +1 -2
  296. package/vendor/abseil-cpp/absl/strings/str_cat_test.cc +28 -0
  297. package/vendor/abseil-cpp/absl/strings/str_join_test.cc +4 -4
  298. package/vendor/abseil-cpp/absl/strings/str_split.h +11 -6
  299. package/vendor/abseil-cpp/absl/strings/str_split_test.cc +13 -0
  300. package/vendor/abseil-cpp/absl/strings/substitute.h +2 -2
  301. package/vendor/abseil-cpp/absl/synchronization/BUILD.bazel +3 -0
  302. package/vendor/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc +21 -0
  303. package/vendor/abseil-cpp/absl/synchronization/internal/per_thread_sem.h +5 -0
  304. package/vendor/abseil-cpp/absl/synchronization/mutex.cc +13 -0
  305. package/vendor/abseil-cpp/absl/synchronization/mutex.h +32 -2
  306. package/vendor/abseil-cpp/absl/synchronization/mutex_test.cc +17 -3
  307. package/vendor/abseil-cpp/absl/time/BUILD.bazel +80 -0
  308. package/vendor/abseil-cpp/absl/time/CMakeLists.txt +73 -0
  309. package/vendor/abseil-cpp/absl/time/clock.h +3 -0
  310. package/vendor/abseil-cpp/absl/time/clock_interface.cc +71 -0
  311. package/vendor/abseil-cpp/absl/time/clock_interface.h +93 -0
  312. package/vendor/abseil-cpp/absl/time/clock_interface_test.cc +128 -0
  313. package/vendor/abseil-cpp/absl/time/format.cc +3 -10
  314. package/vendor/abseil-cpp/absl/time/format_test.cc +12 -0
  315. package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc +90 -89
  316. package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc +80 -5
  317. package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_name_win.cc +1 -2
  318. package/vendor/abseil-cpp/absl/time/internal/cctz/src/tzfile.h +10 -15
  319. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/version +1 -1
  320. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver +0 -0
  321. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh +0 -0
  322. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh +0 -0
  323. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon +0 -0
  324. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi +0 -0
  325. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane +0 -0
  326. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific +0 -0
  327. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau +0 -0
  328. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol +0 -0
  329. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab +1 -1
  330. package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab +3 -3
  331. package/vendor/abseil-cpp/absl/time/simulated_clock.cc +225 -0
  332. package/vendor/abseil-cpp/absl/time/simulated_clock.h +109 -0
  333. package/vendor/abseil-cpp/absl/time/simulated_clock_test.cc +614 -0
  334. package/vendor/abseil-cpp/absl/types/BUILD.bazel +116 -0
  335. package/vendor/abseil-cpp/absl/types/CMakeLists.txt +100 -0
  336. package/vendor/abseil-cpp/absl/types/any.h +26 -4
  337. package/vendor/abseil-cpp/absl/types/any_span.h +1067 -0
  338. package/vendor/abseil-cpp/absl/types/any_span_benchmark.cc +258 -0
  339. package/vendor/abseil-cpp/absl/types/any_span_test.cc +1210 -0
  340. package/vendor/abseil-cpp/absl/types/compare.h +4 -4
  341. package/vendor/abseil-cpp/absl/types/internal/any_span.h +477 -0
  342. package/vendor/abseil-cpp/absl/types/internal/span.h +5 -6
  343. package/vendor/abseil-cpp/absl/types/optional.h +30 -3
  344. package/vendor/abseil-cpp/absl/types/optional_ref.h +295 -0
  345. package/vendor/abseil-cpp/absl/types/optional_ref_test.cc +370 -0
  346. package/vendor/abseil-cpp/absl/types/source_location.cc +18 -0
  347. package/vendor/abseil-cpp/absl/types/source_location.h +172 -0
  348. package/vendor/abseil-cpp/absl/types/source_location_test.cc +139 -0
  349. package/vendor/abseil-cpp/absl/types/span.h +19 -23
  350. package/vendor/abseil-cpp/absl/types/variant.h +75 -18
  351. package/vendor/abseil-cpp/absl/types/variant_test.cc +23 -23
  352. package/vendor/abseil-cpp/absl/utility/BUILD.bazel +1 -0
  353. package/vendor/abseil-cpp/absl/utility/CMakeLists.txt +1 -0
  354. package/vendor/abseil-cpp/absl/utility/utility.h +99 -16
  355. package/vendor/abseil-cpp/ci/absl_alternate_options.h +2 -0
  356. package/vendor/abseil-cpp/ci/linux_arm_clang-latest_libcxx_bazel.sh +10 -4
  357. package/vendor/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh +13 -6
  358. package/vendor/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh +10 -4
  359. package/vendor/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh +12 -5
  360. package/vendor/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh +9 -2
  361. package/vendor/abseil-cpp/ci/linux_docker_containers.sh +4 -4
  362. package/vendor/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh +10 -3
  363. package/vendor/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh +8 -2
  364. package/vendor/abseil-cpp/ci/macos_xcode_bazel.sh +4 -3
  365. package/vendor/abseil-cpp/ci/macos_xcode_cmake.sh +2 -2
  366. package/vendor/abseil-cpp/ci/windows_clangcl_bazel.bat +1 -1
  367. package/vendor/abseil-cpp/ci/windows_msvc_bazel.bat +1 -1
  368. package/vendor/abseil-cpp/absl/debugging/internal/borrowed_fixup_buffer.cc +0 -118
  369. package/vendor/abseil-cpp/absl/debugging/internal/borrowed_fixup_buffer.h +0 -71
  370. package/vendor/abseil-cpp/absl/debugging/internal/borrowed_fixup_buffer_test.cc +0 -97
@@ -221,6 +221,14 @@
221
221
  #include "absl/numeric/bits.h"
222
222
  #include "absl/utility/utility.h"
223
223
 
224
+ #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
225
+ #include <ranges> // NOLINT(build/c++20)
226
+ #endif
227
+
228
+ #ifdef __BMI2__
229
+ #include <bmi2intrin.h>
230
+ #endif // __BMI2__
231
+
224
232
  namespace absl {
225
233
  ABSL_NAMESPACE_BEGIN
226
234
  namespace container_internal {
@@ -297,57 +305,6 @@ void CopyAlloc(AllocType& lhs, AllocType& rhs,
297
305
  template <typename AllocType>
298
306
  void CopyAlloc(AllocType&, AllocType&, std::false_type /* propagate_alloc */) {}
299
307
 
300
- // The state for a probe sequence.
301
- //
302
- // Currently, the sequence is a triangular progression of the form
303
- //
304
- // p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)
305
- //
306
- // The use of `Width` ensures that each probe step does not overlap groups;
307
- // the sequence effectively outputs the addresses of *groups* (although not
308
- // necessarily aligned to any boundary). The `Group` machinery allows us
309
- // to check an entire group with minimal branching.
310
- //
311
- // Wrapping around at `mask + 1` is important, but not for the obvious reason.
312
- // As described above, the first few entries of the control byte array
313
- // are mirrored at the end of the array, which `Group` will find and use
314
- // for selecting candidates. However, when those candidates' slots are
315
- // actually inspected, there are no corresponding slots for the cloned bytes,
316
- // so we need to make sure we've treated those offsets as "wrapping around".
317
- //
318
- // It turns out that this probe sequence visits every group exactly once if the
319
- // number of groups is a power of two, since (i^2+i)/2 is a bijection in
320
- // Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing
321
- template <size_t Width>
322
- class probe_seq {
323
- public:
324
- // Creates a new probe sequence using `hash` as the initial value of the
325
- // sequence and `mask` (usually the capacity of the table) as the mask to
326
- // apply to each value in the progression.
327
- probe_seq(size_t hash, size_t mask) {
328
- ABSL_SWISSTABLE_ASSERT(((mask + 1) & mask) == 0 && "not a mask");
329
- mask_ = mask;
330
- offset_ = hash & mask_;
331
- }
332
-
333
- // The offset within the table, i.e., the value `p(i)` above.
334
- size_t offset() const { return offset_; }
335
- size_t offset(size_t i) const { return (offset_ + i) & mask_; }
336
-
337
- void next() {
338
- index_ += Width;
339
- offset_ += index_;
340
- offset_ &= mask_;
341
- }
342
- // 0-based probe index, a multiple of `Width`.
343
- size_t index() const { return index_; }
344
-
345
- private:
346
- size_t mask_;
347
- size_t offset_;
348
- size_t index_ = 0;
349
- };
350
-
351
308
  template <class ContainerKey, class Hash, class Eq>
352
309
  struct RequireUsableKey {
353
310
  template <class PassedKey, class... Args>
@@ -363,25 +320,13 @@ struct IsDecomposable : std::false_type {};
363
320
 
364
321
  template <class Policy, class Hash, class Eq, class... Ts>
365
322
  struct IsDecomposable<
366
- absl::void_t<decltype(Policy::apply(
323
+ std::void_t<decltype(Policy::apply(
367
324
  RequireUsableKey<typename Policy::key_type, Hash, Eq>(),
368
325
  std::declval<Ts>()...))>,
369
326
  Policy, Hash, Eq, Ts...> : std::true_type {};
370
327
 
371
328
  ABSL_DLL extern ctrl_t kDefaultIterControl;
372
329
 
373
- // We use these sentinel capacity values in debug mode to indicate different
374
- // classes of bugs.
375
- enum InvalidCapacity : size_t {
376
- kAboveMaxValidCapacity = ~size_t{} - 100,
377
- kReentrance,
378
- kDestroyed,
379
-
380
- // These two must be last because we use `>= kMovedFrom` to mean moved-from.
381
- kMovedFrom,
382
- kSelfMovedFrom,
383
- };
384
-
385
330
  // Returns a pointer to a control byte that can be used by default-constructed
386
331
  // iterators. We don't expect this pointer to be dereferenced.
387
332
  inline ctrl_t* DefaultIterControl() { return &kDefaultIterControl; }
@@ -417,6 +362,8 @@ inline bool IsEmptyGeneration(const GenerationType* generation) {
417
362
  // - In order to prevent user code from depending on iteration order for small
418
363
  // tables, we would need to randomize the iteration order somehow.
419
364
  constexpr size_t SooCapacity() { return 1; }
365
+ // Maximum capacity of a table where we don't need to hash any keys.
366
+ constexpr size_t MaxSmallCapacity() { return 1; }
420
367
  // Sentinel type to indicate SOO CommonFields construction.
421
368
  struct soo_tag_t {};
422
369
  // Sentinel type to indicate SOO CommonFields construction with full size.
@@ -428,74 +375,308 @@ struct uninitialized_tag_t {};
428
375
  // Sentinel value to indicate creation of an empty table without a seed.
429
376
  struct no_seed_empty_tag_t {};
430
377
 
378
+ // Returns whether `n` is a valid capacity (i.e., number of slots).
379
+ //
380
+ // A valid capacity is a non-zero integer `2^m - 1`.
381
+ constexpr bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
382
+
383
+ // Whether a table is small enough that we don't need to hash any keys.
384
+ constexpr bool IsSmallCapacity(size_t capacity) {
385
+ return capacity <= MaxSmallCapacity();
386
+ }
387
+
388
+ // Converts `n` into the next valid capacity, per `IsValidCapacity`.
389
+ constexpr size_t NormalizeCapacity(size_t n) {
390
+ return n ? ~size_t{} >> countl_zero(n) : 1;
391
+ }
392
+
393
+ // Returns the next valid capacity after `n`.
394
+ constexpr size_t NextCapacity(size_t n) {
395
+ ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n) || n == 0);
396
+ return n * 2 + 1;
397
+ }
398
+
399
+ // Returns the previous valid capacity before `n`.
400
+ constexpr size_t PreviousCapacity(size_t n) {
401
+ ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n));
402
+ return n / 2;
403
+ }
404
+
405
+ // General notes on capacity/growth methods below:
406
+ // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
407
+ // average of two empty slots per group.
408
+ // - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
409
+ // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
410
+ // never need to probe (the whole table fits in one group) so we don't need a
411
+ // load factor less than 1.
412
+
413
+ // Given `capacity`, applies the load factor; i.e., it returns the maximum
414
+ // number of values we should put into the table before a resizing rehash.
415
+ constexpr size_t CapacityToGrowth(size_t capacity) {
416
+ ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
417
+ // `capacity*7/8`
418
+ if (Group::kWidth == 8 && capacity == 7) {
419
+ // x-x/8 does not work when x==7.
420
+ return 6;
421
+ }
422
+ return capacity - capacity / 8;
423
+ }
424
+
425
+ // Given `size`, "unapplies" the load factor to find how large the capacity
426
+ // should be to stay within the load factor.
427
+ //
428
+ // For size == 0, returns 0.
429
+ // For other values, returns the same as `NormalizeCapacity(size*8/7)`.
430
+ constexpr size_t SizeToCapacity(size_t size) {
431
+ if (size == 0) {
432
+ return 0;
433
+ }
434
+ // The minimum possible capacity is NormalizeCapacity(size).
435
+ // Shifting right `~size_t{}` by `leading_zeros` yields
436
+ // NormalizeCapacity(size).
437
+ int leading_zeros = absl::countl_zero(size);
438
+ constexpr size_t kLast3Bits = size_t{7} << (sizeof(size_t) * 8 - 3);
439
+ // max_size_for_next_capacity = max_load_factor * next_capacity
440
+ // = (7/8) * (~size_t{} >> leading_zeros)
441
+ // = (7/8*~size_t{}) >> leading_zeros
442
+ // = kLast3Bits >> leading_zeros
443
+ size_t max_size_for_next_capacity = kLast3Bits >> leading_zeros;
444
+ // Decrease shift if size is too big for the minimum capacity.
445
+ leading_zeros -= static_cast<int>(size > max_size_for_next_capacity);
446
+ if constexpr (Group::kWidth == 8) {
447
+ // Formula doesn't work when size==7 for 8-wide groups.
448
+ leading_zeros -= (size == 7);
449
+ }
450
+ return (~size_t{}) >> leading_zeros;
451
+ }
452
+
453
+ // The mode we store capacity in the table.
454
+ enum HashtableCapacityStorageMode {
455
+ // Capacity stored as size_t as a full number.
456
+ kCapacityByValue,
457
+ // Capacity stored as uint8_t as log2, i.e. capacity = 2^capacity_ - 1.
458
+ kCapacityByLog,
459
+ };
460
+
461
+ // The number of slots in the backing array. This is always 2^N-1 for an
462
+ // integer N.
463
+ // NOTE: this class exists to simplify experiments with different ways to store
464
+ // capacity within size.
465
+ // NOTE: we tried experimenting with compressing the capacity and storing it
466
+ // together with size_: (a) using 6 bits to store the corresponding power (N in
467
+ // 2^N-1), and (b) storing 2^N as the most significant bit of size_ and storing
468
+ // size in the low bits. Both of these experiments were regressions, presumably
469
+ // because we need capacity to do find operations.
470
+ template <HashtableCapacityStorageMode StorageMode>
471
+ class HashtableCapacityImpl {
472
+ using IntType =
473
+ std::conditional_t<StorageMode == kCapacityByValue, size_t, uint8_t>;
474
+
475
+ public:
476
+ static constexpr HashtableCapacityImpl CreateDestroyed() {
477
+ return HashtableCapacityImpl(kDestroyed);
478
+ }
479
+ static constexpr HashtableCapacityImpl CreateReentrance() {
480
+ return HashtableCapacityImpl(kReentrance);
481
+ }
482
+ static constexpr HashtableCapacityImpl CreateMovedFrom() {
483
+ return HashtableCapacityImpl(kMovedFrom);
484
+ }
485
+ static constexpr HashtableCapacityImpl CreateSelfMovedFrom() {
486
+ return HashtableCapacityImpl(kSelfMovedFrom);
487
+ }
488
+
489
+ explicit HashtableCapacityImpl(uninitialized_tag_t) {}
490
+ explicit constexpr HashtableCapacityImpl(size_t capacity)
491
+ : capacity_data_(static_cast<IntType>(
492
+ StorageMode == kCapacityByValue ? capacity
493
+ : TrailingZeros(capacity + 1))) {
494
+ ABSL_SWISSTABLE_ASSERT(capacity == 0 || IsValidCapacity(capacity));
495
+ }
496
+
497
+ // Creates capacity from the value that was returned by `ToRawData()`.
498
+ // This is needed to use bitfield for capacity.
499
+ // At least on Windows combination uint8_t and uint64_t bitfield in one struct
500
+ // is not optimized by compiler.
501
+ static HashtableCapacityImpl FromRawData(uint64_t capacity) {
502
+ auto cap = HashtableCapacityImpl(uninitialized_tag_t{});
503
+ cap.capacity_data_ = static_cast<IntType>(capacity);
504
+ return cap;
505
+ }
506
+ IntType ToRawData() const { return capacity_data_; }
507
+
508
+ constexpr bool IsValid() const {
509
+ return capacity_data_ <= kAboveMaxValidCapacity;
510
+ }
511
+
512
+ constexpr bool IsDestroyed() const { return capacity_data_ == kDestroyed; }
513
+ constexpr bool IsReentrance() const { return capacity_data_ == kReentrance; }
514
+ // Returns true if the table is moved-from including self moved-from.
515
+ constexpr bool IsMovedFrom() const { return capacity_data_ >= kMovedFrom; }
516
+ constexpr bool IsSelfMovedFrom() const {
517
+ return capacity_data_ == kSelfMovedFrom;
518
+ }
519
+
520
+ constexpr size_t capacity() const {
521
+ ABSL_SWISSTABLE_ASSERT(IsValid());
522
+ return StorageMode == kCapacityByValue ? capacity_data_
523
+ : (size_t{1} << capacity_data_) - 1;
524
+ }
525
+
526
+ constexpr bool is_small() const {
527
+ // Small tables have capacity 0 or 1. This expression is valid for both
528
+ // capacity storage modes.
529
+ // Comparing capacity_data_ directly leads to a better generated code.
530
+ // One byte comparison is used before computing the capacity in order to
531
+ // detect small tables faster for critical path.
532
+ static_assert(MaxSmallCapacity() == 1);
533
+ return capacity_data_ <= 1;
534
+ }
535
+
536
+ constexpr size_t mask(size_t value) const {
537
+ #ifdef __BMI2__
538
+ if constexpr (StorageMode == kCapacityByLog) {
539
+ if constexpr (sizeof(size_t) == 8) {
540
+ return _bzhi_u64(value, capacity_data_);
541
+ } else {
542
+ return _bzhi_u32(value, capacity_data_);
543
+ }
544
+ }
545
+ #endif // __BMI2__
546
+ return value & capacity();
547
+ }
548
+
549
+ private:
550
+ // We use these sentinel capacity values in debug mode to indicate different
551
+ // classes of bugs.
552
+ enum InvalidCapacity : IntType {
553
+ kAboveMaxValidCapacity = (std::numeric_limits<IntType>::max)() - 100,
554
+ kReentrance,
555
+ kDestroyed,
556
+
557
+ // These two must be last because we use `>= kMovedFrom` to mean moved-from.
558
+ kMovedFrom,
559
+ kSelfMovedFrom,
560
+ };
561
+
562
+ explicit constexpr HashtableCapacityImpl(InvalidCapacity capacity)
563
+ : capacity_data_(capacity) {
564
+ ABSL_SWISSTABLE_ASSERT(capacity_data_ > kAboveMaxValidCapacity);
565
+ }
566
+
567
+ // Capacity is stored as a value or as a log2 depending on `StorageMode`.
568
+ IntType capacity_data_;
569
+ };
570
+
571
+ template <HashtableCapacityStorageMode StorageMode>
572
+ class HashtableInlineDataImpl;
573
+
574
+ // Returns next per-table seed.
575
+ uint16_t NextHashTableSeed();
576
+
431
577
  // Per table hash salt. This gets mixed into H1 to randomize iteration order
432
578
  // per-table.
433
579
  // The seed is needed to ensure non-determinism of iteration order.
434
- class PerTableSeed {
580
+ template <typename StorageType>
581
+ class PerTableSeedImpl {
435
582
  public:
583
+ using IntType = StorageType;
584
+
436
585
  // The number of bits in the seed.
437
586
  // It is big enough to ensure non-determinism of iteration order.
438
587
  // We store the seed inside a uint64_t together with size and other metadata.
439
- // Using 16 bits allows us to save one `and` instruction in H1 (we use
440
- // sign-extended move instead of mov+and).
441
- static constexpr size_t kBitCount = 16;
442
- static constexpr size_t kSignBit = uint64_t{1} << (kBitCount - 1);
588
+ // Using 8 or 16 bits allows us to save one `and` instruction in H1 (we use
589
+ // zero-extended move instead of mov+and). When absl::Hash is inlined, it can
590
+ // also have lower latency knowing that the high bits of the seed are zero.
591
+ static constexpr size_t kBitCount = sizeof(IntType) * 8;
592
+
593
+ // We need to use a constant seed when the table is sampled so that sampled
594
+ // hashes use the same seed and can e.g. identify stuck bits accurately.
595
+ static constexpr IntType kSampledSeed = static_cast<IntType>(~IntType{0});
443
596
 
444
597
  // Returns the seed for the table.
445
- size_t seed() const {
446
- // We use a sign-extended load to ensure high bits are non-zero.
447
- int16_t seed_signed = absl::bit_cast<int16_t>(seed_);
448
- auto seed_sign_extended =
449
- static_cast<std::make_signed_t<size_t>>(seed_signed);
450
- return absl::bit_cast<size_t>(seed_sign_extended);
451
- }
598
+ size_t seed() const { return seed_; }
452
599
 
453
600
  private:
454
- friend class HashtableSize;
455
- explicit PerTableSeed(uint16_t seed) : seed_(seed) {
456
- ABSL_SWISSTABLE_ASSERT((seed & kSignBit) != 0 || seed == 0);
457
- }
601
+ template <HashtableCapacityStorageMode StorageMode>
602
+ friend class HashtableInlineDataImpl;
603
+
604
+ explicit PerTableSeedImpl(uint64_t seed)
605
+ : seed_(static_cast<IntType>(seed)) {}
458
606
 
459
- // The most significant bit of the seed is always 1 when there is a non-zero
460
- // seed. This way, when sign-extended the seed has non-zero high bits.
461
- const uint16_t seed_;
607
+ const IntType seed_;
462
608
  };
463
609
 
464
- // The size and also has additionally
610
+ // Capacity, size and also has additionally
465
611
  // 1) one bit that stores whether we have infoz.
466
- // 2) PerTableSeed::kBitCount bits for the seed.
467
- class HashtableSize {
612
+ // 2) PerTableSeed::kBitCount bits for the seed. (For SOO tables, the lowest
613
+ // bit of the seed is repurposed to track if sampling has been tried).
614
+ template <HashtableCapacityStorageMode StorageMode>
615
+ class HashtableInlineDataImpl {
468
616
  public:
469
- static constexpr size_t kSizeBitCount = 64 - PerTableSeed::kBitCount - 1;
470
-
471
- explicit HashtableSize(uninitialized_tag_t) {}
472
- explicit HashtableSize(no_seed_empty_tag_t) : data_(0) {}
473
- explicit HashtableSize(full_soo_tag_t) : data_(kSizeOneNoMetadata) {}
617
+ static constexpr HashtableCapacityStorageMode kStorageMode = StorageMode;
618
+ using PerTableSeed = PerTableSeedImpl<
619
+ std::conditional_t<StorageMode == kCapacityByValue, uint16_t, uint8_t>>;
620
+ using HashtableCapacity = HashtableCapacityImpl<StorageMode>;
621
+ static constexpr size_t kSizeBitCount =
622
+ StorageMode == kCapacityByValue
623
+ ? 64 - PerTableSeed::kBitCount - 1
624
+ : 64 - PerTableSeed::kBitCount - sizeof(HashtableCapacity) * 8 - 1;
625
+
626
+ explicit HashtableInlineDataImpl(uninitialized_tag_t) {}
627
+ explicit HashtableInlineDataImpl(HashtableCapacity capacity,
628
+ no_seed_empty_tag_t)
629
+ : capacity_internal_(capacity.ToRawData()), data_(0) {}
630
+ HashtableInlineDataImpl(HashtableCapacity capacity, full_soo_tag_t,
631
+ bool has_tried_sampling)
632
+ : capacity_internal_(capacity.ToRawData()),
633
+ data_(kSizeOneNoMetadata |
634
+ (has_tried_sampling ? kSooHasTriedSamplingMask : 0)) {}
635
+
636
+ HashtableCapacity capacity() const {
637
+ return HashtableCapacity::FromRawData(capacity_internal_);
638
+ }
639
+ bool is_small() const { return capacity().is_small(); }
640
+
641
+ void set_capacity(HashtableCapacity c) { capacity_internal_ = c.ToRawData(); }
642
+ void set_capacity(size_t c) { set_capacity(HashtableCapacity(c)); }
474
643
 
475
644
  // Returns actual size of the table.
476
645
  size_t size() const { return static_cast<size_t>(data_ >> kSizeShift); }
477
646
  void increment_size() { data_ += kSizeOneNoMetadata; }
478
647
  void increment_size(size_t size) {
479
- data_ += static_cast<uint64_t>(size) * kSizeOneNoMetadata;
648
+ data_ += static_cast<uint64_t>(size) << kSizeShift;
480
649
  }
481
650
  void decrement_size() { data_ -= kSizeOneNoMetadata; }
482
651
  // Returns true if the table is empty.
483
652
  bool empty() const { return data_ < kSizeOneNoMetadata; }
484
- // Sets the size to zero, but keeps all the metadata bits.
485
- void set_size_to_zero_keep_metadata() { data_ = data_ & kMetadataMask; }
486
653
 
487
- PerTableSeed seed() const {
488
- return PerTableSeed(static_cast<size_t>(data_) & kSeedMask);
654
+ // Returns true if an empty SOO table has already queried should_sample_soo().
655
+ bool soo_has_tried_sampling() const {
656
+ return (data_ & kSooHasTriedSamplingMask) != 0;
657
+ }
658
+
659
+ // Records that an empty SOO table has tried sampling.
660
+ void set_soo_has_tried_sampling() { data_ |= kSooHasTriedSamplingMask; }
661
+
662
+ // Sets the size, but keeps all the metadata bits.
663
+ void set_size(size_t size) {
664
+ data_ =
665
+ (data_ & kMetadataMask) | (static_cast<uint64_t>(size) << kSizeShift);
489
666
  }
490
667
 
491
- void generate_new_seed() { set_seed(NextSeed()); }
668
+ PerTableSeed seed() const { return PerTableSeed(data_ & kSeedMask); }
669
+
670
+ void generate_new_seed() {
671
+ set_seed(static_cast<typename PerTableSeed::IntType>(NextHashTableSeed()));
672
+ }
492
673
 
493
674
  // We need to use a constant seed when the table is sampled so that sampled
494
675
  // hashes use the same seed and can e.g. identify stuck bits accurately.
495
- void set_sampled_seed() { set_seed(PerTableSeed::kSignBit); }
676
+ void set_sampled_seed() { set_seed(PerTableSeed::kSampledSeed); }
496
677
 
497
678
  bool is_sampled_seed() const {
498
- return (data_ & kSeedMask) == PerTableSeed::kSignBit;
679
+ return seed().seed() == PerTableSeed::kSampledSeed;
499
680
  }
500
681
 
501
682
  // Returns true if the table has infoz.
@@ -508,23 +689,53 @@ class HashtableSize {
508
689
 
509
690
  void set_no_seed_for_testing() { data_ &= ~kSeedMask; }
510
691
 
511
- // Returns next per-table seed.
512
- static uint16_t NextSeed();
513
-
514
692
  private:
515
- void set_seed(uint16_t seed) {
516
- data_ = (data_ & ~kSeedMask) | (seed | PerTableSeed::kSignBit);
517
- }
518
- static constexpr size_t kSizeShift = 64 - kSizeBitCount;
693
+ // Bit layout of `data_` from MSB to LSB:
694
+ // (47 bits) : size
695
+ // (1 bit) : has_infoz
696
+ // (16 or 8 bits) : seed
697
+ // We don't split these components of `data_` into separate bit field elements
698
+ // because we get worse generated code that way.
699
+ static constexpr size_t kDataBitCount =
700
+ PerTableSeed::kBitCount + 1 + kSizeBitCount;
701
+ static constexpr size_t kSizeShift = kDataBitCount - kSizeBitCount;
519
702
  static constexpr uint64_t kSizeOneNoMetadata = uint64_t{1} << kSizeShift;
520
703
  static constexpr uint64_t kMetadataMask = kSizeOneNoMetadata - 1;
521
704
  static constexpr uint64_t kSeedMask =
522
705
  (uint64_t{1} << PerTableSeed::kBitCount) - 1;
523
706
  // The next bit after the seed.
524
707
  static constexpr uint64_t kHasInfozMask = kSeedMask + 1;
525
- uint64_t data_;
708
+ // For SOO tables, the seed is unused, and bit 0 is repurposed to track
709
+ // whether the table has already queried should_sample_soo().
710
+ static constexpr uint64_t kSooHasTriedSamplingMask = 1;
711
+
712
+ void set_seed(typename PerTableSeed::IntType seed) {
713
+ data_ = (data_ & ~kSeedMask) | seed;
714
+ }
715
+
716
+ uint64_t capacity_internal_ : sizeof(HashtableCapacity) * 8;
717
+ uint64_t data_ : kDataBitCount;
526
718
  };
527
719
 
720
+ static_assert(
721
+ sizeof(HashtableInlineDataImpl<kCapacityByValue>::HashtableCapacity) ==
722
+ sizeof(size_t));
723
+ // NOTE: some platforms have this size to be equal to 12 for two reasons:
724
+ // 1) alignof(uint64_t) == 4.
725
+ // 2) sizeof(size_t) == sizeof(HashtableCapacityImpl<kCapacityByValue>) == 4.
726
+ static_assert(sizeof(HashtableInlineDataImpl<kCapacityByValue>) <= 16);
727
+ static_assert(
728
+ sizeof(HashtableInlineDataImpl<kCapacityByLog>::HashtableCapacity) == 1);
729
+ static_assert(sizeof(HashtableInlineDataImpl<kCapacityByLog>) == 8);
730
+
731
+ #ifndef ABSL_SWISSTABLE_INTERNAL_ENABLE_CAPACITY_BY_VALUE
732
+ using HashtableInlineData = HashtableInlineDataImpl<kCapacityByLog>;
733
+ #else
734
+ using HashtableInlineData = HashtableInlineDataImpl<kCapacityByValue>;
735
+ #endif // ABSL_SWISSTABLE_INTERNAL_ENABLE_CAPACITY_BY_VALUE
736
+ using PerTableSeed = HashtableInlineData::PerTableSeed;
737
+ using HashtableCapacity = HashtableInlineData::HashtableCapacity;
738
+
528
739
  // H1 is just the low bits of the hash.
529
740
  inline size_t H1(size_t hash) { return hash; }
530
741
 
@@ -766,14 +977,6 @@ class GrowthInfo {
766
977
  static_assert(sizeof(GrowthInfo) == sizeof(size_t), "");
767
978
  static_assert(alignof(GrowthInfo) == alignof(size_t), "");
768
979
 
769
- // Returns whether `n` is a valid capacity (i.e., number of slots).
770
- //
771
- // A valid capacity is a non-zero integer `2^m - 1`.
772
- constexpr bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
773
-
774
- // Whether a table is small enough that we don't need to hash any keys.
775
- constexpr bool IsSmallCapacity(size_t capacity) { return capacity <= 1; }
776
-
777
980
  // Returns the number of "cloned control bytes".
778
981
  //
779
982
  // This is the number of control bytes that are present both at the beginning
@@ -786,10 +989,20 @@ constexpr size_t NumControlBytes(size_t capacity) {
786
989
  return IsSmallCapacity(capacity) ? 0 : capacity + 1 + NumClonedBytes();
787
990
  }
788
991
 
992
+ // Returns whether table with the given capacity has a GrowthInfo.
993
+ constexpr bool HasGrowthInfoForCapacity(size_t capacity) {
994
+ return !IsSmallCapacity(capacity);
995
+ }
996
+
789
997
  // Computes the offset from the start of the backing allocation of control.
790
998
  // infoz and growth_info are stored at the beginning of the backing array.
791
- constexpr size_t ControlOffset(bool has_infoz) {
792
- return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(GrowthInfo);
999
+ constexpr size_t ControlOffset(bool has_infoz, bool has_growth_info) {
1000
+ if (ABSL_PREDICT_FALSE(has_infoz)) {
1001
+ // We always allocate GrowthInfo for sampled tables to allow branchless
1002
+ // access to infoz pointer.
1003
+ return sizeof(HashtablezInfoHandle) + sizeof(GrowthInfo);
1004
+ }
1005
+ return has_growth_info ? sizeof(GrowthInfo) : 0;
793
1006
  }
794
1007
 
795
1008
  // Returns the offset of the next item after `offset` that is aligned to `align`
@@ -801,12 +1014,10 @@ constexpr size_t AlignUpTo(size_t offset, size_t align) {
801
1014
  // Helper class for computing offsets and allocation size of hash set fields.
802
1015
  class RawHashSetLayout {
803
1016
  public:
804
- // TODO(b/413062340): maybe don't allocate growth info for capacity 1 tables.
805
- // Doing so may require additional branches/complexity so it might not be
806
- // worth it.
807
1017
  explicit RawHashSetLayout(size_t capacity, size_t slot_size,
808
1018
  size_t slot_align, bool has_infoz)
809
- : control_offset_(ControlOffset(has_infoz)),
1019
+ : control_offset_(
1020
+ ControlOffset(has_infoz, HasGrowthInfoForCapacity(capacity))),
810
1021
  generation_offset_(control_offset_ + NumControlBytes(capacity)),
811
1022
  slot_offset_(
812
1023
  AlignUpTo(generation_offset_ + NumGenerationBytes(), slot_align)),
@@ -912,13 +1123,15 @@ inline GrowthInfo& GetGrowthInfoFromControl(ctrl_t* control) {
912
1123
  class CommonFields : public CommonFieldsGenerationInfo {
913
1124
  public:
914
1125
  explicit CommonFields(soo_tag_t)
915
- : capacity_(SooCapacity()), size_(no_seed_empty_tag_t{}) {}
916
- explicit CommonFields(full_soo_tag_t)
917
- : capacity_(SooCapacity()), size_(full_soo_tag_t{}) {}
1126
+ : inline_data_(HashtableCapacity(SooCapacity()), no_seed_empty_tag_t{}) {}
1127
+ explicit CommonFields(full_soo_tag_t, bool has_tried_sampling)
1128
+ : inline_data_(HashtableCapacity(SooCapacity()), full_soo_tag_t{},
1129
+ has_tried_sampling) {}
918
1130
  explicit CommonFields(non_soo_tag_t)
919
- : capacity_(0), size_(no_seed_empty_tag_t{}) {}
1131
+ : inline_data_(HashtableCapacity(0), no_seed_empty_tag_t{}) {}
920
1132
  // For use in swapping.
921
- explicit CommonFields(uninitialized_tag_t) : size_(uninitialized_tag_t{}) {}
1133
+ explicit CommonFields(uninitialized_tag_t)
1134
+ : inline_data_(uninitialized_tag_t{}) {}
922
1135
 
923
1136
  // Not copyable
924
1137
  CommonFields(const CommonFields&) = delete;
@@ -926,10 +1139,7 @@ class CommonFields : public CommonFieldsGenerationInfo {
926
1139
 
927
1140
  // Copy with guarantee that it is not SOO.
928
1141
  CommonFields(non_soo_tag_t, const CommonFields& that)
929
- : capacity_(that.capacity_),
930
- size_(that.size_),
931
- heap_or_soo_(that.heap_or_soo_) {
932
- }
1142
+ : inline_data_(that.inline_data_), heap_or_soo_(that.heap_or_soo_) {}
933
1143
 
934
1144
  // Movable
935
1145
  CommonFields(CommonFields&& that) = default;
@@ -967,33 +1177,39 @@ class CommonFields : public CommonFieldsGenerationInfo {
967
1177
  void set_slots(void* s) { heap_or_soo_.slot_array().set(s); }
968
1178
 
969
1179
  // The number of filled slots.
970
- size_t size() const { return size_.size(); }
1180
+ size_t size() const { return inline_data_.size(); }
971
1181
  // Sets the size to zero, but keeps hashinfoz bit and seed.
972
- void set_size_to_zero() { size_.set_size_to_zero_keep_metadata(); }
1182
+ void set_size_to_zero() { inline_data_.set_size(0); }
973
1183
  void set_empty_soo() {
974
1184
  AssertInSooMode();
975
- size_ = HashtableSize(no_seed_empty_tag_t{});
1185
+ inline_data_.set_size(0);
976
1186
  }
977
1187
  void set_full_soo() {
978
1188
  AssertInSooMode();
979
- size_ = HashtableSize(full_soo_tag_t{});
1189
+ inline_data_.set_size(1);
980
1190
  }
981
1191
  void increment_size() {
982
1192
  ABSL_SWISSTABLE_ASSERT(size() < capacity());
983
- size_.increment_size();
1193
+ inline_data_.increment_size();
984
1194
  }
985
1195
  void increment_size(size_t n) {
986
1196
  ABSL_SWISSTABLE_ASSERT(size() + n <= capacity());
987
- size_.increment_size(n);
1197
+ inline_data_.increment_size(n);
988
1198
  }
989
1199
  void decrement_size() {
990
1200
  ABSL_SWISSTABLE_ASSERT(!empty());
991
- size_.decrement_size();
1201
+ inline_data_.decrement_size();
1202
+ }
1203
+ bool empty() const { return inline_data_.empty(); }
1204
+ void set_soo_has_tried_sampling() {
1205
+ inline_data_.set_soo_has_tried_sampling();
1206
+ }
1207
+ bool soo_has_tried_sampling() const {
1208
+ return inline_data_.soo_has_tried_sampling();
992
1209
  }
993
- bool empty() const { return size_.empty(); }
994
1210
 
995
1211
  // The seed used for the hash function.
996
- PerTableSeed seed() const { return size_.seed(); }
1212
+ PerTableSeed seed() const { return inline_data_.seed(); }
997
1213
  // Generates a new seed the hash function.
998
1214
  // The table will be invalidated if `!empty()` because hash is being changed.
999
1215
  // In such cases, we will need to rehash the table.
@@ -1001,22 +1217,29 @@ class CommonFields : public CommonFieldsGenerationInfo {
1001
1217
  // Note: we can't use has_infoz() here because we set has_infoz later than
1002
1218
  // we generate the seed.
1003
1219
  if (ABSL_PREDICT_FALSE(has_infoz)) {
1004
- size_.set_sampled_seed();
1220
+ inline_data_.set_sampled_seed();
1005
1221
  return;
1006
1222
  }
1007
- size_.generate_new_seed();
1223
+ inline_data_.generate_new_seed();
1008
1224
  }
1009
- void set_no_seed_for_testing() { size_.set_no_seed_for_testing(); }
1225
+ void set_no_seed_for_testing() { inline_data_.set_no_seed_for_testing(); }
1010
1226
 
1011
- // The total number of available slots.
1012
- size_t capacity() const { return capacity_; }
1227
+ HashtableCapacity capacity_impl() const {
1228
+ HashtableCapacity cap = inline_data_.capacity();
1229
+ ABSL_SWISSTABLE_ASSERT(cap.IsValid());
1230
+ return cap;
1231
+ }
1232
+ size_t capacity() const { return capacity_impl().capacity(); }
1233
+ // We have a separate alias for callsites in which the capacity may be
1234
+ // invalid.
1235
+ HashtableCapacity maybe_invalid_capacity() const {
1236
+ return inline_data_.capacity();
1237
+ }
1238
+ void set_capacity(HashtableCapacity c) { inline_data_.set_capacity(c); }
1013
1239
  void set_capacity(size_t c) {
1014
- // We allow setting above the max valid capacity for debugging purposes.
1015
- ABSL_SWISSTABLE_ASSERT(c == 0 || IsValidCapacity(c) ||
1016
- c > kAboveMaxValidCapacity);
1017
- capacity_ = c;
1240
+ set_capacity(HashtableCapacity(c));
1018
1241
  }
1019
- bool is_small() const { return IsSmallCapacity(capacity_); }
1242
+ bool is_small() const { return inline_data_.is_small(); }
1020
1243
 
1021
1244
  // The number of slots we can still fill without needing to rehash.
1022
1245
  // This is stored in the heap allocation before the control bytes.
@@ -1025,17 +1248,17 @@ class CommonFields : public CommonFieldsGenerationInfo {
1025
1248
  size_t growth_left() const { return growth_info().GetGrowthLeft(); }
1026
1249
 
1027
1250
  GrowthInfo& growth_info() {
1028
- ABSL_SWISSTABLE_ASSERT(!is_small());
1251
+ ABSL_SWISSTABLE_ASSERT(HasGrowthInfoForCapacity(capacity()));
1029
1252
  return GetGrowthInfoFromControl(control());
1030
1253
  }
1031
1254
  GrowthInfo growth_info() const {
1032
1255
  return const_cast<CommonFields*>(this)->growth_info();
1033
1256
  }
1034
1257
 
1035
- bool has_infoz() const { return size_.has_infoz(); }
1258
+ bool has_infoz() const { return inline_data_.has_infoz(); }
1036
1259
  void set_has_infoz() {
1037
- ABSL_SWISSTABLE_ASSERT(size_.is_sampled_seed());
1038
- size_.set_has_infoz();
1260
+ ABSL_SWISSTABLE_ASSERT(inline_data_.is_sampled_seed());
1261
+ inline_data_.set_has_infoz();
1039
1262
  }
1040
1263
 
1041
1264
  HashtablezInfoHandle* infoz_ptr() const {
@@ -1044,7 +1267,8 @@ class CommonFields : public CommonFieldsGenerationInfo {
1044
1267
  reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
1045
1268
  ABSL_SWISSTABLE_ASSERT(has_infoz());
1046
1269
  return reinterpret_cast<HashtablezInfoHandle*>(
1047
- control() - ControlOffset(/*has_infoz=*/true));
1270
+ control() - ControlOffset(/*has_infoz=*/true,
1271
+ HasGrowthInfoForCapacity(capacity())));
1048
1272
  }
1049
1273
 
1050
1274
  HashtablezInfoHandle infoz() {
@@ -1083,8 +1307,7 @@ class CommonFields : public CommonFieldsGenerationInfo {
1083
1307
  void move_non_heap_or_soo_fields(CommonFields& that) {
1084
1308
  static_cast<CommonFieldsGenerationInfo&>(*this) =
1085
1309
  std::move(static_cast<CommonFieldsGenerationInfo&>(that));
1086
- capacity_ = that.capacity_;
1087
- size_ = that.size_;
1310
+ inline_data_ = that.inline_data_;
1088
1311
  }
1089
1312
 
1090
1313
  // Returns the number of control bytes set to kDeleted. For testing only.
@@ -1101,8 +1324,8 @@ class CommonFields : public CommonFieldsGenerationInfo {
1101
1324
  f();
1102
1325
  return;
1103
1326
  #endif
1104
- const size_t cap = capacity();
1105
- set_capacity(InvalidCapacity::kReentrance);
1327
+ const HashtableCapacity cap = maybe_invalid_capacity();
1328
+ set_capacity(HashtableCapacity::CreateReentrance());
1106
1329
  f();
1107
1330
  set_capacity(cap);
1108
1331
  }
@@ -1121,18 +1344,10 @@ class CommonFields : public CommonFieldsGenerationInfo {
1121
1344
  ABSL_SWISSTABLE_ASSERT(!has_infoz());
1122
1345
  }
1123
1346
 
1124
- // The number of slots in the backing array. This is always 2^N-1 for an
1125
- // integer N. NOTE: we tried experimenting with compressing the capacity and
1126
- // storing it together with size_: (a) using 6 bits to store the corresponding
1127
- // power (N in 2^N-1), and (b) storing 2^N as the most significant bit of
1128
- // size_ and storing size in the low bits. Both of these experiments were
1129
- // regressions, presumably because we need capacity to do find operations.
1130
- size_t capacity_;
1131
-
1132
1347
  // TODO(b/289225379): we could put size_ into HeapOrSoo and make capacity_
1133
1348
  // encode the size in SOO case. We would be making size()/capacity() more
1134
1349
  // expensive in order to have more SOO space.
1135
- HashtableSize size_;
1350
+ HashtableInlineData inline_data_;
1136
1351
 
1137
1352
  // Either the control/slots pointers or the SOO slot.
1138
1353
  HeapOrSoo heap_or_soo_;
@@ -1141,18 +1356,6 @@ class CommonFields : public CommonFieldsGenerationInfo {
1141
1356
  template <class Policy, class... Params>
1142
1357
  class raw_hash_set;
1143
1358
 
1144
- // Returns the next valid capacity after `n`.
1145
- constexpr size_t NextCapacity(size_t n) {
1146
- ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n) || n == 0);
1147
- return n * 2 + 1;
1148
- }
1149
-
1150
- // Returns the previous valid capacity before `n`.
1151
- constexpr size_t PreviousCapacity(size_t n) {
1152
- ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n));
1153
- return n / 2;
1154
- }
1155
-
1156
1359
  // Applies the following mapping to every byte in the control array:
1157
1360
  // * kDeleted -> kEmpty
1158
1361
  // * kEmpty -> kEmpty
@@ -1163,59 +1366,6 @@ constexpr size_t PreviousCapacity(size_t n) {
1163
1366
  // ctrl[i] != ctrl_t::kSentinel for all i < capacity
1164
1367
  void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
1165
1368
 
1166
- // Converts `n` into the next valid capacity, per `IsValidCapacity`.
1167
- constexpr size_t NormalizeCapacity(size_t n) {
1168
- return n ? ~size_t{} >> countl_zero(n) : 1;
1169
- }
1170
-
1171
- // General notes on capacity/growth methods below:
1172
- // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
1173
- // average of two empty slots per group.
1174
- // - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
1175
- // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
1176
- // never need to probe (the whole table fits in one group) so we don't need a
1177
- // load factor less than 1.
1178
-
1179
- // Given `capacity`, applies the load factor; i.e., it returns the maximum
1180
- // number of values we should put into the table before a resizing rehash.
1181
- constexpr size_t CapacityToGrowth(size_t capacity) {
1182
- ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
1183
- // `capacity*7/8`
1184
- if (Group::kWidth == 8 && capacity == 7) {
1185
- // x-x/8 does not work when x==7.
1186
- return 6;
1187
- }
1188
- return capacity - capacity / 8;
1189
- }
1190
-
1191
- // Given `size`, "unapplies" the load factor to find how large the capacity
1192
- // should be to stay within the load factor.
1193
- //
1194
- // For size == 0, returns 0.
1195
- // For other values, returns the same as `NormalizeCapacity(size*8/7)`.
1196
- constexpr size_t SizeToCapacity(size_t size) {
1197
- if (size == 0) {
1198
- return 0;
1199
- }
1200
- // The minimum possible capacity is NormalizeCapacity(size).
1201
- // Shifting right `~size_t{}` by `leading_zeros` yields
1202
- // NormalizeCapacity(size).
1203
- int leading_zeros = absl::countl_zero(size);
1204
- constexpr size_t kLast3Bits = size_t{7} << (sizeof(size_t) * 8 - 3);
1205
- // max_size_for_next_capacity = max_load_factor * next_capacity
1206
- // = (7/8) * (~size_t{} >> leading_zeros)
1207
- // = (7/8*~size_t{}) >> leading_zeros
1208
- // = kLast3Bits >> leading_zeros
1209
- size_t max_size_for_next_capacity = kLast3Bits >> leading_zeros;
1210
- // Decrease shift if size is too big for the minimum capacity.
1211
- leading_zeros -= static_cast<int>(size > max_size_for_next_capacity);
1212
- if constexpr (Group::kWidth == 8) {
1213
- // Formula doesn't work when size==7 for 8-wide groups.
1214
- leading_zeros -= (size == 7);
1215
- }
1216
- return (~size_t{}) >> leading_zeros;
1217
- }
1218
-
1219
1369
  template <class InputIter>
1220
1370
  size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
1221
1371
  size_t bucket_count) {
@@ -1238,6 +1388,26 @@ constexpr bool SwisstableDebugEnabled() {
1238
1388
  #endif
1239
1389
  }
1240
1390
 
1391
+ // Dereferences `ptr`. The function is named in order to provide a helpful error
1392
+ // message when users see crashing stack traces. Note that this function is not
1393
+ // guaranteed to crash when `ptr` is invalid if sanitizer mode is not enabled.
1394
+ template <typename T>
1395
+ T CrashIfIteratorIsInvalid(const T* ptr) {
1396
+ // If the following line(s) crash, then it's likely that `ptr` is from a
1397
+ // backing array that has been deallocated. If you see a crash here, it likely
1398
+ // means that you are comparing an invalid iterator from a table that has
1399
+ // rehashed, moved, or been destroyed. In such cases, it is often helpful to
1400
+ // reproduce the issue with --config=asan and (assuming there's a crash here)
1401
+ // examine the corresponding deallocation stack trace.
1402
+ T ret = *ptr;
1403
+ // Force a read with inline asm to make sure that a crash happens here, rather
1404
+ // than later when the value is used.
1405
+ #ifdef __clang__
1406
+ asm("" : "+r"(ret));
1407
+ #endif
1408
+ return ret;
1409
+ }
1410
+
1241
1411
  inline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation,
1242
1412
  const GenerationType* generation_ptr,
1243
1413
  const char* operation) {
@@ -1255,20 +1425,21 @@ inline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation,
1255
1425
  operation);
1256
1426
  }
1257
1427
  if (SwisstableGenerationsEnabled()) {
1258
- if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {
1428
+ if (ABSL_PREDICT_FALSE(generation !=
1429
+ CrashIfIteratorIsInvalid(generation_ptr))) {
1259
1430
  ABSL_RAW_LOG(FATAL,
1260
1431
  "%s called on invalid iterator. The table could have "
1261
1432
  "rehashed or moved since this iterator was initialized.",
1262
1433
  operation);
1263
1434
  }
1264
- if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {
1435
+ if (ABSL_PREDICT_FALSE(!IsFull(CrashIfIteratorIsInvalid(ctrl)))) {
1265
1436
  ABSL_RAW_LOG(
1266
1437
  FATAL,
1267
1438
  "%s called on invalid iterator. The element was likely erased.",
1268
1439
  operation);
1269
1440
  }
1270
1441
  } else {
1271
- if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {
1442
+ if (ABSL_PREDICT_FALSE(!IsFull(CrashIfIteratorIsInvalid(ctrl)))) {
1272
1443
  ABSL_RAW_LOG(
1273
1444
  FATAL,
1274
1445
  "%s called on invalid iterator. The element might have been erased "
@@ -1285,12 +1456,19 @@ inline void AssertIsValidForComparison(const ctrl_t* ctrl,
1285
1456
  const GenerationType* generation_ptr) {
1286
1457
  if (!SwisstableDebugEnabled()) return;
1287
1458
  const bool ctrl_is_valid_for_comparison =
1288
- ctrl == nullptr || ctrl == DefaultIterControl() || IsFull(*ctrl);
1459
+ ctrl == nullptr || ctrl == DefaultIterControl() ||
1460
+ IsFull(CrashIfIteratorIsInvalid(ctrl));
1289
1461
  if (SwisstableGenerationsEnabled()) {
1290
- if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {
1291
- ABSL_RAW_LOG(FATAL,
1292
- "Invalid iterator comparison. The table could have rehashed "
1293
- "or moved since this iterator was initialized.");
1462
+ if (ABSL_PREDICT_FALSE(generation !=
1463
+ CrashIfIteratorIsInvalid(generation_ptr))) {
1464
+ // Note: in the case of a rehash, we would expect to see a sanitizer crash
1465
+ // in CrashIfIteratorIsInvalid so this assertion will only catch moved
1466
+ // table cases, unless we're using a custom allocator that does not
1467
+ // deallocate the old backing array (e.g. an arena allocator).
1468
+ ABSL_RAW_LOG(
1469
+ FATAL,
1470
+ "Invalid iterator comparison. The table was likely moved (or "
1471
+ "possibly rehashed) since this iterator was initialized.");
1294
1472
  }
1295
1473
  if (ABSL_PREDICT_FALSE(!ctrl_is_valid_for_comparison)) {
1296
1474
  ABSL_RAW_LOG(
@@ -1394,15 +1572,64 @@ constexpr bool is_single_group(size_t capacity) {
1394
1572
  return capacity <= Group::kWidth;
1395
1573
  }
1396
1574
 
1575
+ // The state for a probe sequence.
1576
+ //
1577
+ // Currently, the sequence is a triangular progression of the form
1578
+ //
1579
+ // p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)
1580
+ //
1581
+ // The use of `Width` ensures that each probe step does not overlap groups;
1582
+ // the sequence effectively outputs the addresses of *groups* (although not
1583
+ // necessarily aligned to any boundary). The `Group` machinery allows us
1584
+ // to check an entire group with minimal branching.
1585
+ //
1586
+ // Wrapping around at `mask + 1` is important, but not for the obvious reason.
1587
+ // As described above, the first few entries of the control byte array
1588
+ // are mirrored at the end of the array, which `Group` will find and use
1589
+ // for selecting candidates. However, when those candidates' slots are
1590
+ // actually inspected, there are no corresponding slots for the cloned bytes,
1591
+ // so we need to make sure we've treated those offsets as "wrapping around".
1592
+ //
1593
+ // It turns out that this probe sequence visits every group exactly once if the
1594
+ // number of groups is a power of two, since (i^2+i)/2 is a bijection in
1595
+ // Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing
1596
+ template <size_t Width>
1597
+ class probe_seq {
1598
+ public:
1599
+ // Creates a new probe sequence using `hash` as the initial value of the
1600
+ // sequence and `capacity` as the mask to apply to each value in the
1601
+ // progression.
1602
+ probe_seq(HashtableCapacity capacity, size_t hash)
1603
+ : capacity_(capacity), offset_(capacity.mask(hash)) {}
1604
+
1605
+ // The offset within the table, i.e., the value `p(i)` above.
1606
+ size_t offset() const { return offset_; }
1607
+ size_t offset(size_t i) const { return capacity_.mask(offset_ + i); }
1608
+
1609
+ void next() {
1610
+ index_ += Width;
1611
+ offset_ += index_;
1612
+ offset_ = capacity_.mask(offset_);
1613
+ }
1614
+ // 0-based probe index, a multiple of `Width`.
1615
+ size_t index() const { return index_; }
1616
+
1617
+ private:
1618
+ HashtableCapacity capacity_;
1619
+ size_t offset_;
1620
+ size_t index_ = 0;
1621
+ };
1622
+
1397
1623
  // Begins a probing operation on `common.control`, using `hash`.
1398
- inline probe_seq<Group::kWidth> probe_h1(size_t capacity, size_t h1) {
1399
- return probe_seq<Group::kWidth>(h1, capacity);
1624
+ inline probe_seq<Group::kWidth> probe_h1(HashtableCapacity capacity,
1625
+ size_t h1) {
1626
+ return probe_seq<Group::kWidth>(capacity, h1);
1400
1627
  }
1401
- inline probe_seq<Group::kWidth> probe(size_t capacity, size_t hash) {
1628
+ inline probe_seq<Group::kWidth> probe(HashtableCapacity capacity, size_t hash) {
1402
1629
  return probe_h1(capacity, H1(hash));
1403
1630
  }
1404
1631
  inline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {
1405
- return probe(common.capacity(), hash);
1632
+ return probe(common.capacity_impl(), hash);
1406
1633
  }
1407
1634
 
1408
1635
  constexpr size_t kProbedElementIndexSentinel = ~size_t{};
@@ -1563,51 +1790,54 @@ struct PolicyFunctions {
1563
1790
  }
1564
1791
  };
1565
1792
 
1566
- // Returns the maximum valid size for a table with 1-byte slots.
1567
- // This function is an utility shared by MaxValidSize and IsAboveValidSize.
1568
- // Template parameter is only used to enable testing.
1793
+ // The following functions are used for calculating the max valid size of the
1794
+ // table. This is important for security to avoid overflowing size_t when
1795
+ // calculating the allocation size of the backing array
1796
+ // (https://nvd.nist.gov/vuln/detail/CVE-2025-0838). We also limit the max valid
1797
+ // size based on the size of the key_type, and this is an optimization because
1798
+ // we ABSL_ASSUME that the size is less than MaxValidSize, which can enable
1799
+ // other optimizations for tables with small keys.
1800
+
1569
1801
  template <size_t kSizeOfSizeT = sizeof(size_t)>
1570
- constexpr size_t MaxValidSizeFor1ByteSlot() {
1571
- if constexpr (kSizeOfSizeT == 8) {
1572
- return CapacityToGrowth(
1573
- static_cast<size_t>(uint64_t{1} << HashtableSize::kSizeBitCount) - 1);
1574
- } else {
1575
- static_assert(kSizeOfSizeT == 4);
1576
- return CapacityToGrowth((size_t{1} << (kSizeOfSizeT * 8 - 2)) - 1);
1577
- }
1802
+ constexpr size_t MaxSizeAtMaxValidCapacity(size_t slot_size) {
1803
+ using SizeT = std::conditional_t<kSizeOfSizeT == 4, uint32_t, uint64_t>;
1804
+ // We shift right by 2 for a safe margin against overflow.
1805
+ constexpr SizeT kMaxValidCapacity = ~SizeT{} >> 2;
1806
+ return CapacityToGrowth(kMaxValidCapacity) / slot_size;
1578
1807
  }
1579
1808
 
1580
- // Returns the maximum valid size for a table with provided slot size.
1581
- // Template parameter is only used to enable testing.
1809
+ constexpr size_t MaxStorableSize() {
1810
+ return static_cast<size_t>(uint64_t{1}
1811
+ << HashtableInlineData::kSizeBitCount) -
1812
+ 1;
1813
+ }
1814
+
1815
+ // There are no more than 2^sizeof(key_type) unique key_types (and hashtable
1816
+ // keys must be unique) so we can't have a hashtable with more than
1817
+ // 2^sizeof(key_type) elements.
1582
1818
  template <size_t kSizeOfSizeT = sizeof(size_t)>
1583
- constexpr size_t MaxValidSize(size_t slot_size) {
1819
+ constexpr size_t MaxValidSizeForKeySize(size_t key_size) {
1820
+ if (key_size < kSizeOfSizeT) return size_t{1} << 8 * key_size;
1821
+ return (std::numeric_limits<size_t>::max)();
1822
+ }
1823
+
1824
+ template <size_t kSizeOfSizeT = sizeof(size_t)>
1825
+ constexpr size_t MaxValidSizeForSlotSize(size_t slot_size) {
1584
1826
  if constexpr (kSizeOfSizeT == 8) {
1585
- // For small slot sizes we are limited by HashtableSize::kSizeBitCount.
1586
- if (slot_size < size_t{1} << (64 - HashtableSize::kSizeBitCount)) {
1587
- return MaxValidSizeFor1ByteSlot<kSizeOfSizeT>();
1827
+ // For small slot sizes we are limited by HashtableStackData::kSizeBitCount.
1828
+ if (slot_size < size_t{1} << (64 - HashtableInlineData::kSizeBitCount)) {
1829
+ return MaxStorableSize();
1588
1830
  }
1589
- return (size_t{1} << (kSizeOfSizeT * 8 - 2)) / slot_size;
1590
- } else {
1591
- return MaxValidSizeFor1ByteSlot<kSizeOfSizeT>() / slot_size;
1592
1831
  }
1832
+ return MaxSizeAtMaxValidCapacity<kSizeOfSizeT>(slot_size);
1593
1833
  }
1594
1834
 
1595
- // Returns true if size is larger than the maximum valid size.
1596
- // It is an optimization to avoid the division operation in the common case.
1835
+ // Returns the maximum valid size for a table, given the key size and slot size.
1597
1836
  // Template parameter is only used to enable testing.
1598
1837
  template <size_t kSizeOfSizeT = sizeof(size_t)>
1599
- constexpr bool IsAboveValidSize(size_t size, size_t slot_size) {
1600
- if constexpr (kSizeOfSizeT == 8) {
1601
- // For small slot sizes we are limited by HashtableSize::kSizeBitCount.
1602
- if (ABSL_PREDICT_TRUE(slot_size <
1603
- (size_t{1} << (64 - HashtableSize::kSizeBitCount)))) {
1604
- return size > MaxValidSizeFor1ByteSlot<kSizeOfSizeT>();
1605
- }
1606
- return size > MaxValidSize<kSizeOfSizeT>(slot_size);
1607
- } else {
1608
- return uint64_t{size} * slot_size >
1609
- MaxValidSizeFor1ByteSlot<kSizeOfSizeT>();
1610
- }
1838
+ constexpr size_t MaxValidSize(size_t key_size, size_t slot_size) {
1839
+ return (std::min)(MaxValidSizeForKeySize<kSizeOfSizeT>(key_size),
1840
+ MaxValidSizeForSlotSize<kSizeOfSizeT>(slot_size));
1611
1841
  }
1612
1842
 
1613
1843
  // Returns the index of the SOO slot when growing from SOO to non-SOO in a
@@ -1622,8 +1852,9 @@ constexpr size_t SooSlotIndex() { return 1; }
1622
1852
  // Allowing till 16 would require additional store that can be avoided.
1623
1853
  constexpr size_t MaxSmallAfterSooCapacity() { return 7; }
1624
1854
 
1625
- // Type erased version of raw_hash_set::reserve.
1626
- // Requires: `new_size > policy.soo_capacity`.
1855
+ // Type erased version of raw_hash_set::reserve. Requires:
1856
+ // 1. `new_size > policy.soo_capacity`.
1857
+ // 2. `new_size <= kMaxValidSize`.
1627
1858
  void ReserveTableToFitNewSize(CommonFields& common,
1628
1859
  const PolicyFunctions& policy, size_t new_size);
1629
1860
 
@@ -1632,11 +1863,13 @@ void ReserveTableToFitNewSize(CommonFields& common,
1632
1863
  // 1. `c.capacity() == policy.soo_capacity`.
1633
1864
  // 2. `c.empty()`.
1634
1865
  // 3. `new_size > policy.soo_capacity`.
1866
+ // 4. `bucket_count <= MaxValidCapacity()`.
1635
1867
  // The table will be attempted to be sampled.
1636
1868
  void ReserveEmptyNonAllocatedTableToFitBucketCount(
1637
1869
  CommonFields& common, const PolicyFunctions& policy, size_t bucket_count);
1638
1870
 
1639
1871
  // Type erased version of raw_hash_set::rehash.
1872
+ // Requires: `n <= MaxValidCapacity()`.
1640
1873
  void Rehash(CommonFields& common, const PolicyFunctions& policy, size_t n);
1641
1874
 
1642
1875
  // Type erased version of copy constructor.
@@ -1705,9 +1938,9 @@ void ResizeAllocatedTableWithSeedChange(CommonFields& common,
1705
1938
 
1706
1939
  // ClearBackingArray clears the backing array, either modifying it in place,
1707
1940
  // or creating a new one based on the value of "reuse".
1708
- // REQUIRES: c.capacity > 0
1941
+ // REQUIRES: c.capacity > MaxSmallCapacity().
1709
1942
  void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
1710
- void* alloc, bool reuse, bool soo_enabled);
1943
+ void* alloc, bool reuse);
1711
1944
 
1712
1945
  // Type-erased versions of raw_hash_set::erase_meta_only_{small,large}.
1713
1946
  void EraseMetaOnlySmall(CommonFields& c, bool soo_enabled, size_t slot_size);
@@ -1828,9 +2061,9 @@ class raw_hash_set {
1828
2061
  using value_type = typename PolicyTraits::value_type;
1829
2062
  using reference = value_type&;
1830
2063
  using const_reference = const value_type&;
1831
- using pointer = typename absl::allocator_traits<
2064
+ using pointer = typename std::allocator_traits<
1832
2065
  allocator_type>::template rebind_traits<value_type>::pointer;
1833
- using const_pointer = typename absl::allocator_traits<
2066
+ using const_pointer = typename std::allocator_traits<
1834
2067
  allocator_type>::template rebind_traits<value_type>::const_pointer;
1835
2068
 
1836
2069
  private:
@@ -1862,13 +2095,23 @@ class raw_hash_set {
1862
2095
  constexpr static size_t DefaultCapacity() {
1863
2096
  return SooEnabled() ? SooCapacity() : 0;
1864
2097
  }
2098
+ constexpr static size_t MaxValidSize() {
2099
+ return container_internal::MaxValidSize(sizeof(key_type),
2100
+ sizeof(slot_type));
2101
+ }
2102
+ constexpr static size_t MaxValidCapacity() {
2103
+ return SizeToCapacity(MaxValidSize());
2104
+ }
1865
2105
 
1866
2106
  // Whether `size` fits in the SOO capacity of this table.
1867
2107
  bool fits_in_soo(size_t size) const {
1868
2108
  return SooEnabled() && size <= SooCapacity();
1869
2109
  }
1870
2110
  // Whether this table is in SOO mode or non-SOO mode.
1871
- bool is_soo() const { return fits_in_soo(capacity()); }
2111
+ bool is_soo() const {
2112
+ HashtableCapacity cap = maybe_invalid_capacity();
2113
+ return cap.IsValid() && fits_in_soo(cap.capacity());
2114
+ }
1872
2115
  bool is_full_soo() const { return is_soo() && !empty(); }
1873
2116
 
1874
2117
  bool is_small() const { return common().is_small(); }
@@ -1884,15 +2127,15 @@ class raw_hash_set {
1884
2127
  static_assert(sizeof(key_hash_result) >= sizeof(size_t),
1885
2128
  "`Hash::operator()` should return a `size_t`");
1886
2129
 
1887
- using AllocTraits = absl::allocator_traits<allocator_type>;
1888
- using SlotAlloc = typename absl::allocator_traits<
2130
+ using AllocTraits = std::allocator_traits<allocator_type>;
2131
+ using SlotAlloc = typename std::allocator_traits<
1889
2132
  allocator_type>::template rebind_alloc<slot_type>;
1890
2133
  // People are often sloppy with the exact type of their allocator (sometimes
1891
2134
  // it has an extra const or is missing the pair, but rebinds made it work
1892
2135
  // anyway).
1893
2136
  using CharAlloc =
1894
- typename absl::allocator_traits<Alloc>::template rebind_alloc<char>;
1895
- using SlotAllocTraits = typename absl::allocator_traits<
2137
+ typename std::allocator_traits<Alloc>::template rebind_alloc<char>;
2138
+ using SlotAllocTraits = typename std::allocator_traits<
1896
2139
  allocator_type>::template rebind_traits<slot_type>;
1897
2140
 
1898
2141
  static_assert(std::is_lvalue_reference<reference>::value,
@@ -1901,7 +2144,7 @@ class raw_hash_set {
1901
2144
  // An enabler for insert(T&&): T must be convertible to init_type or be the
1902
2145
  // same as [cv] value_type [ref].
1903
2146
  template <class T>
1904
- using Insertable = absl::disjunction<
2147
+ using Insertable = std::disjunction<
1905
2148
  std::is_same<absl::remove_cvref_t<reference>, absl::remove_cvref_t<T>>,
1906
2149
  std::is_convertible<T, init_type>>;
1907
2150
  template <class T>
@@ -1941,9 +2184,9 @@ class raw_hash_set {
1941
2184
  using iterator_category = std::forward_iterator_tag;
1942
2185
  using value_type = typename raw_hash_set::value_type;
1943
2186
  using reference =
1944
- absl::conditional_t<PolicyTraits::constant_iterators::value,
2187
+ std::conditional_t<PolicyTraits::constant_iterators::value,
1945
2188
  const value_type&, value_type&>;
1946
- using pointer = absl::remove_reference_t<reference>*;
2189
+ using pointer = std::remove_reference_t<reference>*;
1947
2190
  using difference_type = typename raw_hash_set::difference_type;
1948
2191
 
1949
2192
  iterator() {}
@@ -2116,7 +2359,8 @@ class raw_hash_set {
2116
2359
  alloc) {
2117
2360
  if (bucket_count > DefaultCapacity()) {
2118
2361
  ReserveEmptyNonAllocatedTableToFitBucketCount(
2119
- common(), GetPolicyFunctions(), bucket_count);
2362
+ common(), GetPolicyFunctions(),
2363
+ (std::min)(bucket_count, MaxValidCapacity()));
2120
2364
  }
2121
2365
  }
2122
2366
 
@@ -2149,6 +2393,28 @@ class raw_hash_set {
2149
2393
  const allocator_type& alloc)
2150
2394
  : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}
2151
2395
 
2396
+ #if defined(__cpp_lib_containers_ranges) && \
2397
+ __cpp_lib_containers_ranges >= 202202L
2398
+ template <typename R>
2399
+ raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count = 0,
2400
+ const hasher& hash = hasher(), const key_equal& eq = key_equal(),
2401
+ const allocator_type& alloc = allocator_type())
2402
+ : raw_hash_set(std::begin(rg), std::end(rg), bucket_count, hash, eq,
2403
+ alloc) {}
2404
+
2405
+ template <typename R>
2406
+ raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count,
2407
+ const allocator_type& alloc)
2408
+ : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count,
2409
+ hasher(), key_equal(), alloc) {}
2410
+
2411
+ template <typename R>
2412
+ raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count,
2413
+ const hasher& hash, const allocator_type& alloc)
2414
+ : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count, hash,
2415
+ key_equal(), alloc) {}
2416
+ #endif
2417
+
2152
2418
  template <class InputIter>
2153
2419
  raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)
2154
2420
  : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
@@ -2243,7 +2509,8 @@ class raw_hash_set {
2243
2509
  // Note: we avoid using exchange for better generated code.
2244
2510
  settings_(PolicyTraits::transfer_uses_memcpy() || !that.is_full_soo()
2245
2511
  ? std::move(that.common())
2246
- : CommonFields{full_soo_tag_t{}},
2512
+ : CommonFields{full_soo_tag_t{},
2513
+ that.common().soo_has_tried_sampling()},
2247
2514
  that.hash_ref(), that.eq_ref(), that.char_alloc_ref()) {
2248
2515
  if (!PolicyTraits::transfer_uses_memcpy() && that.is_full_soo()) {
2249
2516
  transfer(soo_slot(), that.soo_slot());
@@ -2294,7 +2561,7 @@ class raw_hash_set {
2294
2561
  ~raw_hash_set() {
2295
2562
  destructor_impl();
2296
2563
  if constexpr (SwisstableAssertAccessToDestroyedTable()) {
2297
- common().set_capacity(InvalidCapacity::kDestroyed);
2564
+ common().set_capacity(HashtableCapacity::CreateDestroyed());
2298
2565
  }
2299
2566
  }
2300
2567
 
@@ -2326,21 +2593,27 @@ class raw_hash_set {
2326
2593
  bool empty() const { return !size(); }
2327
2594
  size_t size() const {
2328
2595
  AssertNotDebugCapacity();
2329
- return common().size();
2596
+ const size_t size = common().size();
2597
+ [[maybe_unused]] const size_t kMaxValidSize = MaxValidSize();
2598
+ ABSL_ASSUME(size <= kMaxValidSize);
2599
+ return size;
2330
2600
  }
2331
2601
  size_t capacity() const {
2332
2602
  const size_t cap = common().capacity();
2333
- // Compiler complains when using functions in ASSUME so use local variable.
2334
- [[maybe_unused]] static constexpr size_t kDefaultCapacity =
2335
- DefaultCapacity();
2603
+ // Compiler complains when using functions in ASSUME so use local variables.
2604
+ [[maybe_unused]] const bool kIsValid = IsValidCapacity(cap);
2605
+ [[maybe_unused]] const size_t kDefaultCapacity = DefaultCapacity();
2606
+ [[maybe_unused]] const size_t kMaxValidCapacity = MaxValidCapacity();
2607
+ ABSL_ASSUME(kIsValid || cap == 0);
2336
2608
  ABSL_ASSUME(cap >= kDefaultCapacity);
2609
+ ABSL_ASSUME(cap <= kMaxValidCapacity);
2337
2610
  return cap;
2338
2611
  }
2339
- size_t max_size() const { return MaxValidSize(sizeof(slot_type)); }
2612
+ size_t max_size() const { return MaxValidSize(); }
2340
2613
 
2341
2614
  ABSL_ATTRIBUTE_REINITIALIZES void clear() {
2342
2615
  if (SwisstableGenerationsEnabled() &&
2343
- capacity() >= InvalidCapacity::kMovedFrom) {
2616
+ maybe_invalid_capacity().IsMovedFrom()) {
2344
2617
  common().set_capacity(DefaultCapacity());
2345
2618
  }
2346
2619
  AssertNotDebugCapacity();
@@ -2644,8 +2917,8 @@ class raw_hash_set {
2644
2917
  iterator erase(const_iterator first,
2645
2918
  const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2646
2919
  AssertNotDebugCapacity();
2647
- // We check for empty first because clear_backing_array requires that
2648
- // capacity() > 0 as a precondition.
2920
+ // We check for empty and for is_small because clear_backing_array requires
2921
+ // that capacity() > MaxSmallCapacity() as a precondition.
2649
2922
  if (empty()) return end();
2650
2923
  if (first == last) return last.inner_;
2651
2924
  if (is_small()) {
@@ -2736,11 +3009,14 @@ class raw_hash_set {
2736
3009
  typename AllocTraits::propagate_on_container_swap{});
2737
3010
  }
2738
3011
 
2739
- void rehash(size_t n) { Rehash(common(), GetPolicyFunctions(), n); }
3012
+ void rehash(size_t n) {
3013
+ Rehash(common(), GetPolicyFunctions(), (std::min)(n, MaxValidCapacity()));
3014
+ }
2740
3015
 
2741
3016
  void reserve(size_t n) {
2742
3017
  if (ABSL_PREDICT_TRUE(n > DefaultCapacity())) {
2743
- ReserveTableToFitNewSize(common(), GetPolicyFunctions(), n);
3018
+ ReserveTableToFitNewSize(common(), GetPolicyFunctions(),
3019
+ (std::min)(n, MaxValidSize()));
2744
3020
  }
2745
3021
  }
2746
3022
 
@@ -2974,19 +3250,31 @@ class raw_hash_set {
2974
3250
  }
2975
3251
  }
2976
3252
 
2977
- // Returns true if the table needs to be sampled.
3253
+ // Returns true if the table needs to be sampled. This keeps track of whether
3254
+ // sampling has already been evaluated and ensures that it can only return
3255
+ // true on its first evaluation. All subsequent calls will return false.
3256
+ //
2978
3257
  // This should be called on insertion into an empty SOO table and in copy
2979
3258
  // construction when the size can fit in SOO capacity.
2980
- bool should_sample_soo() const {
3259
+ bool should_sample_soo() {
2981
3260
  ABSL_SWISSTABLE_ASSERT(is_soo());
2982
- if (!ShouldSampleHashtablezInfoForAlloc<CharAlloc>()) return false;
3261
+ if constexpr (!ShouldSampleHashtablezInfoForAlloc<CharAlloc>()) {
3262
+ return false;
3263
+ }
3264
+ if (common().soo_has_tried_sampling()) {
3265
+ // Already evaluated sampling on this SOO table; do not re-evaluate
3266
+ // sampling each time it transitions from empty to full SOO state.
3267
+ return false;
3268
+ }
3269
+ // TODO: b/396049910 -- consider managing this flag on the 1->0 size
3270
+ // transition of SOO tables rather than the 0->1 transition.
3271
+ common().set_soo_has_tried_sampling();
2983
3272
  return ABSL_PREDICT_FALSE(ShouldSampleNextTable());
2984
3273
  }
2985
3274
 
2986
3275
  void clear_backing_array(bool reuse) {
2987
- ABSL_SWISSTABLE_ASSERT(capacity() > DefaultCapacity());
2988
- ClearBackingArray(common(), GetPolicyFunctions(), &char_alloc_ref(), reuse,
2989
- SooEnabled());
3276
+ ABSL_SWISSTABLE_ASSERT(capacity() > MaxSmallCapacity());
3277
+ ClearBackingArray(common(), GetPolicyFunctions(), &char_alloc_ref(), reuse);
2990
3278
  }
2991
3279
 
2992
3280
  void destroy_slots() {
@@ -2997,7 +3285,7 @@ class raw_hash_set {
2997
3285
  };
2998
3286
  if constexpr (SwisstableAssertAccessToDestroyedTable()) {
2999
3287
  CommonFields common_copy(non_soo_tag_t{}, this->common());
3000
- common().set_capacity(InvalidCapacity::kDestroyed);
3288
+ common().set_capacity(HashtableCapacity::CreateDestroyed());
3001
3289
  IterateOverFullSlots(common_copy, sizeof(slot_type), destroy_slot);
3002
3290
  common().set_capacity(common_copy.capacity());
3003
3291
  } else {
@@ -3018,7 +3306,7 @@ class raw_hash_set {
3018
3306
 
3019
3307
  void destructor_impl() {
3020
3308
  if (SwisstableGenerationsEnabled() &&
3021
- capacity() >= InvalidCapacity::kMovedFrom) {
3309
+ maybe_invalid_capacity().IsMovedFrom()) {
3022
3310
  return;
3023
3311
  }
3024
3312
  if (capacity() == 0) return;
@@ -3113,11 +3401,13 @@ class raw_hash_set {
3113
3401
  // than using NDEBUG) to avoid issues in which NDEBUG is enabled in some
3114
3402
  // translation units but not in others.
3115
3403
  if (SwisstableGenerationsEnabled()) {
3116
- that.common().set_capacity(this == &that ? InvalidCapacity::kSelfMovedFrom
3117
- : InvalidCapacity::kMovedFrom);
3404
+ that.common().set_capacity(this == &that
3405
+ ? HashtableCapacity::CreateSelfMovedFrom()
3406
+ : HashtableCapacity::CreateMovedFrom());
3118
3407
  }
3119
- if (!SwisstableGenerationsEnabled() || capacity() == DefaultCapacity() ||
3120
- capacity() > kAboveMaxValidCapacity) {
3408
+ if (!SwisstableGenerationsEnabled() ||
3409
+ !maybe_invalid_capacity().IsValid() ||
3410
+ capacity() == DefaultCapacity()) {
3121
3411
  return;
3122
3412
  }
3123
3413
  common().increment_generation();
@@ -3211,7 +3501,6 @@ class raw_hash_set {
3211
3501
  }
3212
3502
  if (!empty()) {
3213
3503
  if (equal_to(key, single_slot())) {
3214
- common().infoz().RecordInsertHit();
3215
3504
  return {single_iterator(), false};
3216
3505
  }
3217
3506
  }
@@ -3243,7 +3532,6 @@ class raw_hash_set {
3243
3532
  if (ABSL_PREDICT_TRUE(equal_to(key, slot_array() + seq.offset(i)))) {
3244
3533
  index = seq.offset(i);
3245
3534
  inserted = false;
3246
- common().infoz().RecordInsertHit();
3247
3535
  return;
3248
3536
  }
3249
3537
  }
@@ -3288,21 +3576,21 @@ class raw_hash_set {
3288
3576
  return;
3289
3577
  }
3290
3578
  #endif
3291
- if (ABSL_PREDICT_TRUE(capacity() <
3292
- InvalidCapacity::kAboveMaxValidCapacity)) {
3579
+ const HashtableCapacity cap = maybe_invalid_capacity();
3580
+ if (ABSL_PREDICT_TRUE(cap.IsValid())) {
3293
3581
  return;
3294
3582
  }
3295
- assert(capacity() != InvalidCapacity::kReentrance &&
3583
+ assert(!cap.IsReentrance() &&
3296
3584
  "Reentrant container access during element construction/destruction "
3297
3585
  "is not allowed.");
3298
3586
  if constexpr (SwisstableAssertAccessToDestroyedTable()) {
3299
- if (capacity() == InvalidCapacity::kDestroyed) {
3587
+ if (cap.IsDestroyed()) {
3300
3588
  ABSL_RAW_LOG(FATAL, "Use of destroyed hash table.");
3301
3589
  }
3302
3590
  }
3303
3591
  if (SwisstableGenerationsEnabled() &&
3304
- ABSL_PREDICT_FALSE(capacity() >= InvalidCapacity::kMovedFrom)) {
3305
- if (capacity() == InvalidCapacity::kSelfMovedFrom) {
3592
+ ABSL_PREDICT_FALSE(cap.IsMovedFrom())) {
3593
+ if (cap.IsSelfMovedFrom()) {
3306
3594
  // If this log triggers, then a hash table was move-assigned to itself
3307
3595
  // and then used again later without being reinitialized.
3308
3596
  ABSL_RAW_LOG(FATAL, "Use of self-move-assigned hash table.");
@@ -3430,6 +3718,11 @@ class raw_hash_set {
3430
3718
  CommonFields& common() { return settings_.template get<0>(); }
3431
3719
  const CommonFields& common() const { return settings_.template get<0>(); }
3432
3720
 
3721
+ // For use when the capacity is potentially invalid we return
3722
+ // HashtableCapacity directly.
3723
+ HashtableCapacity maybe_invalid_capacity() const {
3724
+ return common().maybe_invalid_capacity();
3725
+ }
3433
3726
  ctrl_t* control() const {
3434
3727
  ABSL_SWISSTABLE_ASSERT(!is_soo());
3435
3728
  return common().control();
@@ -3676,7 +3969,7 @@ void ForEach(Callback& cb, const raw_hash_set<P, Params...>* c) {
3676
3969
 
3677
3970
  namespace hashtable_debug_internal {
3678
3971
  template <typename Set>
3679
- struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
3972
+ struct HashtableDebugAccess<Set, std::void_t<typename Set::raw_hash_set>> {
3680
3973
  using Traits = typename Set::PolicyTraits;
3681
3974
  using Slot = typename Traits::slot_type;
3682
3975