ruby_memprofiler_pprof 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. checksums.yaml +7 -0
  2. data/ext/ruby_memprofiler_pprof/backtrace.c +429 -0
  3. data/ext/ruby_memprofiler_pprof/collector.c +1055 -0
  4. data/ext/ruby_memprofiler_pprof/compat.c +182 -0
  5. data/ext/ruby_memprofiler_pprof/extconf.rb +72 -0
  6. data/ext/ruby_memprofiler_pprof/pprof.upb.c +170 -0
  7. data/ext/ruby_memprofiler_pprof/pprof.upb.h +848 -0
  8. data/ext/ruby_memprofiler_pprof/pprof_out.c +285 -0
  9. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.c +11 -0
  10. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.h +301 -0
  11. data/ext/ruby_memprofiler_pprof/strtab.c +391 -0
  12. data/ext/ruby_memprofiler_pprof/vendor/upb/BUILD +719 -0
  13. data/ext/ruby_memprofiler_pprof/vendor/upb/CONTRIBUTING.md +37 -0
  14. data/ext/ruby_memprofiler_pprof/vendor/upb/DESIGN.md +201 -0
  15. data/ext/ruby_memprofiler_pprof/vendor/upb/LICENSE +26 -0
  16. data/ext/ruby_memprofiler_pprof/vendor/upb/README.md +78 -0
  17. data/ext/ruby_memprofiler_pprof/vendor/upb/WORKSPACE +58 -0
  18. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/BUILD +53 -0
  19. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/amalgamate.py +129 -0
  20. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/build_defs.bzl +160 -0
  21. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/lua.BUILD +127 -0
  22. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/protobuf.patch +54 -0
  23. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/py_proto_library.bzl +137 -0
  24. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/python_downloads.bzl +84 -0
  25. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/system_python.bzl +101 -0
  26. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/upb_proto_library.bzl +388 -0
  27. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/workspace_deps.bzl +89 -0
  28. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD +252 -0
  29. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD.googleapis +54 -0
  30. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/benchmark.cc +333 -0
  31. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/build_defs.bzl +88 -0
  32. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/compare.py +118 -0
  33. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor.proto +888 -0
  34. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor_sv.proto +890 -0
  35. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/empty.proto +6 -0
  36. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_protobuf_binary_cc.py +64 -0
  37. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_synthetic_protos.py +118 -0
  38. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_upb_binary_c.py +65 -0
  39. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/BUILD.bazel +102 -0
  40. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/README.md +23 -0
  41. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/build_defs.bzl +73 -0
  42. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/make_cmakelists.py +340 -0
  43. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test.py +57 -0
  44. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test_lib.py +186 -0
  45. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/render.py +43 -0
  46. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/style-guide.md +65 -0
  47. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/vs-cpp-protos.md +255 -0
  48. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/wrapping-upb.md +444 -0
  49. data/ext/ruby_memprofiler_pprof/vendor/upb/python/BUILD +216 -0
  50. data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.c +394 -0
  51. data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.h +63 -0
  52. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.c +1694 -0
  53. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.h +80 -0
  54. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.c +704 -0
  55. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.h +114 -0
  56. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.c +650 -0
  57. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.h +48 -0
  58. data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/BUILD.bazel +193 -0
  59. data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/dist.bzl +190 -0
  60. data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.c +247 -0
  61. data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.h +39 -0
  62. data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.c +522 -0
  63. data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.h +66 -0
  64. data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.c +1909 -0
  65. data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.h +101 -0
  66. data/ext/ruby_memprofiler_pprof/vendor/upb/python/minimal_test.py +183 -0
  67. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/BUILD +70 -0
  68. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/README.md +11 -0
  69. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_database_test_wrapper.py +30 -0
  70. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_pool_test_wrapper.py +45 -0
  71. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_test_wrapper.py +46 -0
  72. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/generator_test_wrapper.py +30 -0
  73. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/json_format_test_wrapper.py +30 -0
  74. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/keywords_test_wrapper.py +30 -0
  75. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_factory_test_wrapper.py +37 -0
  76. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_test_wrapper.py +52 -0
  77. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/proto_builder_test_wrapper.py +32 -0
  78. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/pyproto_test_wrapper.bzl +36 -0
  79. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/reflection_test_wrapper.py +45 -0
  80. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/service_reflection_test_wrapper.py +30 -0
  81. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/symbol_database_test_wrapper.py +30 -0
  82. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_encoding_test_wrapper.py +30 -0
  83. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_format_test_wrapper.py +30 -0
  84. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/unknown_fields_test_wrapper.py +30 -0
  85. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/well_known_types_test_wrapper.py +36 -0
  86. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/wire_format_test_wrapper.py +30 -0
  87. data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.c +350 -0
  88. data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.h +230 -0
  89. data/ext/ruby_memprofiler_pprof/vendor/upb/python/py_extension.bzl +55 -0
  90. data/ext/ruby_memprofiler_pprof/vendor/upb/python/python_api.h +61 -0
  91. data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.c +828 -0
  92. data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.h +69 -0
  93. data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.c +404 -0
  94. data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.h +39 -0
  95. data/ext/ruby_memprofiler_pprof/vendor/upb/python/version_script.lds +6 -0
  96. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/LICENSE +32 -0
  97. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/README.google +9 -0
  98. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/console.lua +156 -0
  99. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/lunit.lua +725 -0
  100. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/BUILD +19 -0
  101. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/LICENSE +21 -0
  102. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/naive.c +92 -0
  103. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-neon.c +157 -0
  104. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-sse.c +170 -0
  105. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/utf8_range.h +9 -0
  106. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/BUILD.bazel +129 -0
  107. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/README.md +8 -0
  108. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/def.c +939 -0
  109. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/lua_proto_library.bzl +138 -0
  110. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/main.c +83 -0
  111. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/msg.c +1118 -0
  112. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test.proto +69 -0
  113. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test_upb.lua +846 -0
  114. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.c +258 -0
  115. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.h +132 -0
  116. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.lua +58 -0
  117. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upbc.cc +134 -0
  118. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.c +192 -0
  119. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.h +174 -0
  120. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb.c +346 -0
  121. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb_failures.txt +1 -0
  122. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.c +1221 -0
  123. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.h +94 -0
  124. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.c +1055 -0
  125. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.h +153 -0
  126. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_internal.h +211 -0
  127. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.c +3262 -0
  128. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.h +414 -0
  129. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.hpp +438 -0
  130. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/empty.proto +1 -0
  131. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.c +604 -0
  132. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.h +71 -0
  133. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/BUILD +13 -0
  134. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/file_descriptor_parsenew_fuzzer.cc +43 -0
  135. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.c +1509 -0
  136. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.h +47 -0
  137. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.c +776 -0
  138. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.h +62 -0
  139. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.c +1147 -0
  140. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.h +189 -0
  141. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.hpp +112 -0
  142. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.c +363 -0
  143. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.h +263 -0
  144. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_internal.h +59 -0
  145. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_test.cc +425 -0
  146. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_test.cc +230 -0
  147. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.c +428 -0
  148. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.h +114 -0
  149. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_internal.h +836 -0
  150. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.cc +491 -0
  151. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.proto +195 -0
  152. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_def.inc +261 -0
  153. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_undef.inc +62 -0
  154. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.c +323 -0
  155. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.h +109 -0
  156. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.hpp +37 -0
  157. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table.c +926 -0
  158. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table_internal.h +385 -0
  159. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test.proto +74 -0
  160. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.cc +186 -0
  161. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.proto +12 -0
  162. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_generated_code.cc +977 -0
  163. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_table.cc +580 -0
  164. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.c +472 -0
  165. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.h +64 -0
  166. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.c +362 -0
  167. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.h +378 -0
  168. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.hpp +115 -0
  169. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb_internal.h +68 -0
  170. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/BUILD +121 -0
  171. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/README.md +7 -0
  172. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.c +300 -0
  173. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.h +66 -0
  174. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare_test.cc +236 -0
  175. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.c +572 -0
  176. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.h +62 -0
  177. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_public_import_test.proto +32 -0
  178. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_regular_import_test.proto +36 -0
  179. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.cc +143 -0
  180. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.proto +119 -0
  181. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_weak_import_test.proto +28 -0
  182. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_wweak_import_test.proto +28 -0
  183. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.c +311 -0
  184. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.h +94 -0
  185. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.cc +202 -0
  186. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.proto +48 -0
  187. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/BUILD +78 -0
  188. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.cc +77 -0
  189. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.h +112 -0
  190. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upb.cc +1997 -0
  191. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upbdefs.cc +193 -0
  192. data/lib/ruby_memprofiler_pprof/atfork.rb +77 -0
  193. data/lib/ruby_memprofiler_pprof/block_flusher.rb +61 -0
  194. data/lib/ruby_memprofiler_pprof/file_flusher.rb +45 -0
  195. data/lib/ruby_memprofiler_pprof/profile_app.rb +30 -0
  196. data/lib/ruby_memprofiler_pprof/profile_data.rb +18 -0
  197. data/lib/ruby_memprofiler_pprof/version.rb +5 -0
  198. data/lib/ruby_memprofiler_pprof.rb +8 -0
  199. data/libexec/ruby_memprofiler_pprof_profile +16 -0
  200. metadata +257 -0
@@ -0,0 +1,926 @@
1
+ /*
2
+ * Copyright (c) 2009-2021, Google LLC
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ * * Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * * Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * * Neither the name of Google LLC nor the
13
+ * names of its contributors may be used to endorse or promote products
14
+ * derived from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ /*
29
+ * upb_table Implementation
30
+ *
31
+ * Implementation is heavily inspired by Lua's ltable.c.
32
+ */
33
+
34
+ #include <string.h>
35
+
36
+ #include "upb/table_internal.h"
37
+
38
+ /* Must be last. */
39
+ #include "upb/port_def.inc"
40
+
41
+ #define UPB_MAXARRSIZE 16 /* 64k. */
42
+
43
+ /* From Chromium. */
44
+ #define ARRAY_SIZE(x) \
45
+ ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x])))))
46
+
47
+ static const double MAX_LOAD = 0.85;
48
+
49
+ /* The minimum utilization of the array part of a mixed hash/array table. This
50
+ * is a speed/memory-usage tradeoff (though it's not straightforward because of
51
+ * cache effects). The lower this is, the more memory we'll use. */
52
+ static const double MIN_DENSITY = 0.1;
53
+
54
+ static bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
55
+
56
+ static upb_value _upb_value_val(uint64_t val) {
57
+ upb_value ret;
58
+ _upb_value_setval(&ret, val);
59
+ return ret;
60
+ }
61
+
62
+ static int log2ceil(uint64_t v) {
63
+ int ret = 0;
64
+ bool pow2 = is_pow2(v);
65
+ while (v >>= 1) ret++;
66
+ ret = pow2 ? ret : ret + 1; /* Ceiling. */
67
+ return UPB_MIN(UPB_MAXARRSIZE, ret);
68
+ }
69
+
70
+ char* upb_strdup2(const char* s, size_t len, upb_Arena* a) {
71
+ size_t n;
72
+ char* p;
73
+
74
+ /* Prevent overflow errors. */
75
+ if (len == SIZE_MAX) return NULL;
76
+ /* Always null-terminate, even if binary data; but don't rely on the input to
77
+ * have a null-terminating byte since it may be a raw binary buffer. */
78
+ n = len + 1;
79
+ p = upb_Arena_Malloc(a, n);
80
+ if (p) {
81
+ memcpy(p, s, len);
82
+ p[len] = 0;
83
+ }
84
+ return p;
85
+ }
86
+
87
+ /* A type to represent the lookup key of either a strtable or an inttable. */
88
+ typedef union {
89
+ uintptr_t num;
90
+ struct {
91
+ const char* str;
92
+ size_t len;
93
+ } str;
94
+ } lookupkey_t;
95
+
96
+ static lookupkey_t strkey2(const char* str, size_t len) {
97
+ lookupkey_t k;
98
+ k.str.str = str;
99
+ k.str.len = len;
100
+ return k;
101
+ }
102
+
103
+ static lookupkey_t intkey(uintptr_t key) {
104
+ lookupkey_t k;
105
+ k.num = key;
106
+ return k;
107
+ }
108
+
109
+ typedef uint32_t hashfunc_t(upb_tabkey key);
110
+ typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
111
+
112
+ /* Base table (shared code) ***************************************************/
113
+
114
+ static uint32_t upb_inthash(uintptr_t key) { return (uint32_t)key; }
115
+
116
+ static const upb_tabent* upb_getentry(const upb_table* t, uint32_t hash) {
117
+ return t->entries + (hash & t->mask);
118
+ }
119
+
120
+ static bool upb_arrhas(upb_tabval key) { return key.val != (uint64_t)-1; }
121
+
122
+ static bool isfull(upb_table* t) { return t->count == t->max_count; }
123
+
124
+ static bool init(upb_table* t, uint8_t size_lg2, upb_Arena* a) {
125
+ size_t bytes;
126
+
127
+ t->count = 0;
128
+ t->size_lg2 = size_lg2;
129
+ t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
130
+ t->max_count = upb_table_size(t) * MAX_LOAD;
131
+ bytes = upb_table_size(t) * sizeof(upb_tabent);
132
+ if (bytes > 0) {
133
+ t->entries = upb_Arena_Malloc(a, bytes);
134
+ if (!t->entries) return false;
135
+ memset(t->entries, 0, bytes);
136
+ } else {
137
+ t->entries = NULL;
138
+ }
139
+ return true;
140
+ }
141
+
142
+ static upb_tabent* emptyent(upb_table* t, upb_tabent* e) {
143
+ upb_tabent* begin = t->entries;
144
+ upb_tabent* end = begin + upb_table_size(t);
145
+ for (e = e + 1; e < end; e++) {
146
+ if (upb_tabent_isempty(e)) return e;
147
+ }
148
+ for (e = begin; e < end; e++) {
149
+ if (upb_tabent_isempty(e)) return e;
150
+ }
151
+ UPB_ASSERT(false);
152
+ return NULL;
153
+ }
154
+
155
+ static upb_tabent* getentry_mutable(upb_table* t, uint32_t hash) {
156
+ return (upb_tabent*)upb_getentry(t, hash);
157
+ }
158
+
159
+ static const upb_tabent* findentry(const upb_table* t, lookupkey_t key,
160
+ uint32_t hash, eqlfunc_t* eql) {
161
+ const upb_tabent* e;
162
+
163
+ if (t->size_lg2 == 0) return NULL;
164
+ e = upb_getentry(t, hash);
165
+ if (upb_tabent_isempty(e)) return NULL;
166
+ while (1) {
167
+ if (eql(e->key, key)) return e;
168
+ if ((e = e->next) == NULL) return NULL;
169
+ }
170
+ }
171
+
172
+ static upb_tabent* findentry_mutable(upb_table* t, lookupkey_t key,
173
+ uint32_t hash, eqlfunc_t* eql) {
174
+ return (upb_tabent*)findentry(t, key, hash, eql);
175
+ }
176
+
177
+ static bool lookup(const upb_table* t, lookupkey_t key, upb_value* v,
178
+ uint32_t hash, eqlfunc_t* eql) {
179
+ const upb_tabent* e = findentry(t, key, hash, eql);
180
+ if (e) {
181
+ if (v) {
182
+ _upb_value_setval(v, e->val.val);
183
+ }
184
+ return true;
185
+ } else {
186
+ return false;
187
+ }
188
+ }
189
+
190
+ /* The given key must not already exist in the table. */
191
+ static void insert(upb_table* t, lookupkey_t key, upb_tabkey tabkey,
192
+ upb_value val, uint32_t hash, hashfunc_t* hashfunc,
193
+ eqlfunc_t* eql) {
194
+ upb_tabent* mainpos_e;
195
+ upb_tabent* our_e;
196
+
197
+ UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
198
+
199
+ t->count++;
200
+ mainpos_e = getentry_mutable(t, hash);
201
+ our_e = mainpos_e;
202
+
203
+ if (upb_tabent_isempty(mainpos_e)) {
204
+ /* Our main position is empty; use it. */
205
+ our_e->next = NULL;
206
+ } else {
207
+ /* Collision. */
208
+ upb_tabent* new_e = emptyent(t, mainpos_e);
209
+ /* Head of collider's chain. */
210
+ upb_tabent* chain = getentry_mutable(t, hashfunc(mainpos_e->key));
211
+ if (chain == mainpos_e) {
212
+ /* Existing ent is in its main position (it has the same hash as us, and
213
+ * is the head of our chain). Insert to new ent and append to this chain.
214
+ */
215
+ new_e->next = mainpos_e->next;
216
+ mainpos_e->next = new_e;
217
+ our_e = new_e;
218
+ } else {
219
+ /* Existing ent is not in its main position (it is a node in some other
220
+ * chain). This implies that no existing ent in the table has our hash.
221
+ * Evict it (updating its chain) and use its ent for head of our chain. */
222
+ *new_e = *mainpos_e; /* copies next. */
223
+ while (chain->next != mainpos_e) {
224
+ chain = (upb_tabent*)chain->next;
225
+ UPB_ASSERT(chain);
226
+ }
227
+ chain->next = new_e;
228
+ our_e = mainpos_e;
229
+ our_e->next = NULL;
230
+ }
231
+ }
232
+ our_e->key = tabkey;
233
+ our_e->val.val = val.val;
234
+ UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
235
+ }
236
+
237
+ static bool rm(upb_table* t, lookupkey_t key, upb_value* val,
238
+ upb_tabkey* removed, uint32_t hash, eqlfunc_t* eql) {
239
+ upb_tabent* chain = getentry_mutable(t, hash);
240
+ if (upb_tabent_isempty(chain)) return false;
241
+ if (eql(chain->key, key)) {
242
+ /* Element to remove is at the head of its chain. */
243
+ t->count--;
244
+ if (val) _upb_value_setval(val, chain->val.val);
245
+ if (removed) *removed = chain->key;
246
+ if (chain->next) {
247
+ upb_tabent* move = (upb_tabent*)chain->next;
248
+ *chain = *move;
249
+ move->key = 0; /* Make the slot empty. */
250
+ } else {
251
+ chain->key = 0; /* Make the slot empty. */
252
+ }
253
+ return true;
254
+ } else {
255
+ /* Element to remove is either in a non-head position or not in the
256
+ * table. */
257
+ while (chain->next && !eql(chain->next->key, key)) {
258
+ chain = (upb_tabent*)chain->next;
259
+ }
260
+ if (chain->next) {
261
+ /* Found element to remove. */
262
+ upb_tabent* rm = (upb_tabent*)chain->next;
263
+ t->count--;
264
+ if (val) _upb_value_setval(val, chain->next->val.val);
265
+ if (removed) *removed = rm->key;
266
+ rm->key = 0; /* Make the slot empty. */
267
+ chain->next = rm->next;
268
+ return true;
269
+ } else {
270
+ /* Element to remove is not in the table. */
271
+ return false;
272
+ }
273
+ }
274
+ }
275
+
276
+ static size_t next(const upb_table* t, size_t i) {
277
+ do {
278
+ if (++i >= upb_table_size(t)) return SIZE_MAX - 1; /* Distinct from -1. */
279
+ } while (upb_tabent_isempty(&t->entries[i]));
280
+
281
+ return i;
282
+ }
283
+
284
+ static size_t begin(const upb_table* t) { return next(t, -1); }
285
+
286
+ /* upb_strtable ***************************************************************/
287
+
288
+ /* A simple "subclass" of upb_table that only adds a hash function for strings.
289
+ */
290
+
291
+ static upb_tabkey strcopy(lookupkey_t k2, upb_Arena* a) {
292
+ uint32_t len = (uint32_t)k2.str.len;
293
+ char* str = upb_Arena_Malloc(a, k2.str.len + sizeof(uint32_t) + 1);
294
+ if (str == NULL) return 0;
295
+ memcpy(str, &len, sizeof(uint32_t));
296
+ if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
297
+ str[sizeof(uint32_t) + k2.str.len] = '\0';
298
+ return (uintptr_t)str;
299
+ }
300
+
301
+ /* Adapted from ABSL's wyhash. */
302
+
303
+ static uint64_t UnalignedLoad64(const void* p) {
304
+ uint64_t val;
305
+ memcpy(&val, p, 8);
306
+ return val;
307
+ }
308
+
309
+ static uint32_t UnalignedLoad32(const void* p) {
310
+ uint32_t val;
311
+ memcpy(&val, p, 4);
312
+ return val;
313
+ }
314
+
315
+ #if defined(_MSC_VER) && defined(_M_X64)
316
+ #include <intrin.h>
317
+ #endif
318
+
319
+ /* Computes a * b, returning the low 64 bits of the result and storing the high
320
+ * 64 bits in |*high|. */
321
+ static uint64_t upb_umul128(uint64_t v0, uint64_t v1, uint64_t* out_high) {
322
+ #ifdef __SIZEOF_INT128__
323
+ __uint128_t p = v0;
324
+ p *= v1;
325
+ *out_high = (uint64_t)(p >> 64);
326
+ return (uint64_t)p;
327
+ #elif defined(_MSC_VER) && defined(_M_X64)
328
+ return _umul128(v0, v1, out_high);
329
+ #else
330
+ uint64_t a32 = v0 >> 32;
331
+ uint64_t a00 = v0 & 0xffffffff;
332
+ uint64_t b32 = v1 >> 32;
333
+ uint64_t b00 = v1 & 0xffffffff;
334
+ uint64_t high = a32 * b32;
335
+ uint64_t low = a00 * b00;
336
+ uint64_t mid1 = a32 * b00;
337
+ uint64_t mid2 = a00 * b32;
338
+ low += (mid1 << 32) + (mid2 << 32);
339
+ // Omit carry bit, for mixing we do not care about exact numerical precision.
340
+ high += (mid1 >> 32) + (mid2 >> 32);
341
+ *out_high = high;
342
+ return low;
343
+ #endif
344
+ }
345
+
346
+ static uint64_t WyhashMix(uint64_t v0, uint64_t v1) {
347
+ uint64_t high;
348
+ uint64_t low = upb_umul128(v0, v1, &high);
349
+ return low ^ high;
350
+ }
351
+
352
+ static uint64_t Wyhash(const void* data, size_t len, uint64_t seed,
353
+ const uint64_t salt[]) {
354
+ const uint8_t* ptr = (const uint8_t*)data;
355
+ uint64_t starting_length = (uint64_t)len;
356
+ uint64_t current_state = seed ^ salt[0];
357
+
358
+ if (len > 64) {
359
+ // If we have more than 64 bytes, we're going to handle chunks of 64
360
+ // bytes at a time. We're going to build up two separate hash states
361
+ // which we will then hash together.
362
+ uint64_t duplicated_state = current_state;
363
+
364
+ do {
365
+ uint64_t a = UnalignedLoad64(ptr);
366
+ uint64_t b = UnalignedLoad64(ptr + 8);
367
+ uint64_t c = UnalignedLoad64(ptr + 16);
368
+ uint64_t d = UnalignedLoad64(ptr + 24);
369
+ uint64_t e = UnalignedLoad64(ptr + 32);
370
+ uint64_t f = UnalignedLoad64(ptr + 40);
371
+ uint64_t g = UnalignedLoad64(ptr + 48);
372
+ uint64_t h = UnalignedLoad64(ptr + 56);
373
+
374
+ uint64_t cs0 = WyhashMix(a ^ salt[1], b ^ current_state);
375
+ uint64_t cs1 = WyhashMix(c ^ salt[2], d ^ current_state);
376
+ current_state = (cs0 ^ cs1);
377
+
378
+ uint64_t ds0 = WyhashMix(e ^ salt[3], f ^ duplicated_state);
379
+ uint64_t ds1 = WyhashMix(g ^ salt[4], h ^ duplicated_state);
380
+ duplicated_state = (ds0 ^ ds1);
381
+
382
+ ptr += 64;
383
+ len -= 64;
384
+ } while (len > 64);
385
+
386
+ current_state = current_state ^ duplicated_state;
387
+ }
388
+
389
+ // We now have a data `ptr` with at most 64 bytes and the current state
390
+ // of the hashing state machine stored in current_state.
391
+ while (len > 16) {
392
+ uint64_t a = UnalignedLoad64(ptr);
393
+ uint64_t b = UnalignedLoad64(ptr + 8);
394
+
395
+ current_state = WyhashMix(a ^ salt[1], b ^ current_state);
396
+
397
+ ptr += 16;
398
+ len -= 16;
399
+ }
400
+
401
+ // We now have a data `ptr` with at most 16 bytes.
402
+ uint64_t a = 0;
403
+ uint64_t b = 0;
404
+ if (len > 8) {
405
+ // When we have at least 9 and at most 16 bytes, set A to the first 64
406
+ // bits of the input and B to the last 64 bits of the input. Yes, they will
407
+ // overlap in the middle if we are working with less than the full 16
408
+ // bytes.
409
+ a = UnalignedLoad64(ptr);
410
+ b = UnalignedLoad64(ptr + len - 8);
411
+ } else if (len > 3) {
412
+ // If we have at least 4 and at most 8 bytes, set A to the first 32
413
+ // bits and B to the last 32 bits.
414
+ a = UnalignedLoad32(ptr);
415
+ b = UnalignedLoad32(ptr + len - 4);
416
+ } else if (len > 0) {
417
+ // If we have at least 1 and at most 3 bytes, read all of the provided
418
+ // bits into A, with some adjustments.
419
+ a = ((ptr[0] << 16) | (ptr[len >> 1] << 8) | ptr[len - 1]);
420
+ b = 0;
421
+ } else {
422
+ a = 0;
423
+ b = 0;
424
+ }
425
+
426
+ uint64_t w = WyhashMix(a ^ salt[1], b ^ current_state);
427
+ uint64_t z = salt[1] ^ starting_length;
428
+ return WyhashMix(w, z);
429
+ }
430
+
431
+ const uint64_t kWyhashSalt[5] = {
432
+ 0x243F6A8885A308D3ULL, 0x13198A2E03707344ULL, 0xA4093822299F31D0ULL,
433
+ 0x082EFA98EC4E6C89ULL, 0x452821E638D01377ULL,
434
+ };
435
+
436
+ uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed) {
437
+ return Wyhash(p, n, seed, kWyhashSalt);
438
+ }
439
+
440
+ static uint32_t _upb_Hash_NoSeed(const char* p, size_t n) {
441
+ return _upb_Hash(p, n, 0);
442
+ }
443
+
444
+ static uint32_t strhash(upb_tabkey key) {
445
+ uint32_t len;
446
+ char* str = upb_tabstr(key, &len);
447
+ return _upb_Hash_NoSeed(str, len);
448
+ }
449
+
450
+ static bool streql(upb_tabkey k1, lookupkey_t k2) {
451
+ uint32_t len;
452
+ char* str = upb_tabstr(k1, &len);
453
+ return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0);
454
+ }
455
+
456
+ bool upb_strtable_init(upb_strtable* t, size_t expected_size, upb_Arena* a) {
457
+ // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2
458
+ // denominator.
459
+ size_t need_entries = (expected_size + 1) * 1204 / 1024;
460
+ UPB_ASSERT(need_entries >= expected_size * 0.85);
461
+ int size_lg2 = _upb_Log2Ceiling(need_entries);
462
+ return init(&t->t, size_lg2, a);
463
+ }
464
+
465
+ void upb_strtable_clear(upb_strtable* t) {
466
+ size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
467
+ t->t.count = 0;
468
+ memset((char*)t->t.entries, 0, bytes);
469
+ }
470
+
471
+ bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a) {
472
+ upb_strtable new_table;
473
+ upb_strtable_iter i;
474
+
475
+ if (!init(&new_table.t, size_lg2, a)) return false;
476
+ upb_strtable_begin(&i, t);
477
+ for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
478
+ upb_StringView key = upb_strtable_iter_key(&i);
479
+ upb_strtable_insert(&new_table, key.data, key.size,
480
+ upb_strtable_iter_value(&i), a);
481
+ }
482
+ *t = new_table;
483
+ return true;
484
+ }
485
+
486
+ bool upb_strtable_insert(upb_strtable* t, const char* k, size_t len,
487
+ upb_value v, upb_Arena* a) {
488
+ lookupkey_t key;
489
+ upb_tabkey tabkey;
490
+ uint32_t hash;
491
+
492
+ if (isfull(&t->t)) {
493
+ /* Need to resize. New table of double the size, add old elements to it. */
494
+ if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
495
+ return false;
496
+ }
497
+ }
498
+
499
+ key = strkey2(k, len);
500
+ tabkey = strcopy(key, a);
501
+ if (tabkey == 0) return false;
502
+
503
+ hash = _upb_Hash_NoSeed(key.str.str, key.str.len);
504
+ insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
505
+ return true;
506
+ }
507
+
508
+ bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
509
+ upb_value* v) {
510
+ uint32_t hash = _upb_Hash_NoSeed(key, len);
511
+ return lookup(&t->t, strkey2(key, len), v, hash, &streql);
512
+ }
513
+
514
+ bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len,
515
+ upb_value* val) {
516
+ uint32_t hash = _upb_Hash_NoSeed(key, len);
517
+ upb_tabkey tabkey;
518
+ return rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql);
519
+ }
520
+
521
+ /* Iteration */
522
+
523
+ void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t) {
524
+ i->t = t;
525
+ i->index = begin(&t->t);
526
+ }
527
+
528
+ void upb_strtable_next(upb_strtable_iter* i) {
529
+ i->index = next(&i->t->t, i->index);
530
+ }
531
+
532
+ bool upb_strtable_done(const upb_strtable_iter* i) {
533
+ if (!i->t) return true;
534
+ return i->index >= upb_table_size(&i->t->t) ||
535
+ upb_tabent_isempty(str_tabent(i));
536
+ }
537
+
538
+ upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i) {
539
+ upb_StringView key;
540
+ uint32_t len;
541
+ UPB_ASSERT(!upb_strtable_done(i));
542
+ key.data = upb_tabstr(str_tabent(i)->key, &len);
543
+ key.size = len;
544
+ return key;
545
+ }
546
+
547
+ upb_value upb_strtable_iter_value(const upb_strtable_iter* i) {
548
+ UPB_ASSERT(!upb_strtable_done(i));
549
+ return _upb_value_val(str_tabent(i)->val.val);
550
+ }
551
+
552
+ void upb_strtable_iter_setdone(upb_strtable_iter* i) {
553
+ i->t = NULL;
554
+ i->index = SIZE_MAX;
555
+ }
556
+
557
+ bool upb_strtable_iter_isequal(const upb_strtable_iter* i1,
558
+ const upb_strtable_iter* i2) {
559
+ if (upb_strtable_done(i1) && upb_strtable_done(i2)) return true;
560
+ return i1->t == i2->t && i1->index == i2->index;
561
+ }
562
+
563
+ /* upb_inttable ***************************************************************/
564
+
565
+ /* For inttables we use a hybrid structure where small keys are kept in an
566
+ * array and large keys are put in the hash table. */
567
+
568
+ static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
569
+
570
+ static bool inteql(upb_tabkey k1, lookupkey_t k2) { return k1 == k2.num; }
571
+
572
+ static upb_tabval* mutable_array(upb_inttable* t) {
573
+ return (upb_tabval*)t->array;
574
+ }
575
+
576
+ static upb_tabval* inttable_val(upb_inttable* t, uintptr_t key) {
577
+ if (key < t->array_size) {
578
+ return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
579
+ } else {
580
+ upb_tabent* e =
581
+ findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
582
+ return e ? &e->val : NULL;
583
+ }
584
+ }
585
+
586
+ static const upb_tabval* inttable_val_const(const upb_inttable* t,
587
+ uintptr_t key) {
588
+ return inttable_val((upb_inttable*)t, key);
589
+ }
590
+
591
+ size_t upb_inttable_count(const upb_inttable* t) {
592
+ return t->t.count + t->array_count;
593
+ }
594
+
595
+ static void check(upb_inttable* t) {
596
+ UPB_UNUSED(t);
597
+ #if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
598
+ {
599
+ /* This check is very expensive (makes inserts/deletes O(N)). */
600
+ size_t count = 0;
601
+ upb_inttable_iter i;
602
+ upb_inttable_begin(&i, t);
603
+ for (; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
604
+ UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
605
+ }
606
+ UPB_ASSERT(count == upb_inttable_count(t));
607
+ }
608
+ #endif
609
+ }
610
+
611
+ bool upb_inttable_sizedinit(upb_inttable* t, size_t asize, int hsize_lg2,
612
+ upb_Arena* a) {
613
+ size_t array_bytes;
614
+
615
+ if (!init(&t->t, hsize_lg2, a)) return false;
616
+ /* Always make the array part at least 1 long, so that we know key 0
617
+ * won't be in the hash part, which simplifies things. */
618
+ t->array_size = UPB_MAX(1, asize);
619
+ t->array_count = 0;
620
+ array_bytes = t->array_size * sizeof(upb_value);
621
+ t->array = upb_Arena_Malloc(a, array_bytes);
622
+ if (!t->array) {
623
+ return false;
624
+ }
625
+ memset(mutable_array(t), 0xff, array_bytes);
626
+ check(t);
627
+ return true;
628
+ }
629
+
630
+ bool upb_inttable_init(upb_inttable* t, upb_Arena* a) {
631
+ return upb_inttable_sizedinit(t, 0, 4, a);
632
+ }
633
+
634
+ bool upb_inttable_insert(upb_inttable* t, uintptr_t key, upb_value val,
635
+ upb_Arena* a) {
636
+ upb_tabval tabval;
637
+ tabval.val = val.val;
638
+ UPB_ASSERT(
639
+ upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */
640
+
641
+ if (key < t->array_size) {
642
+ UPB_ASSERT(!upb_arrhas(t->array[key]));
643
+ t->array_count++;
644
+ mutable_array(t)[key].val = val.val;
645
+ } else {
646
+ if (isfull(&t->t)) {
647
+ /* Need to resize the hash part, but we re-use the array part. */
648
+ size_t i;
649
+ upb_table new_table;
650
+
651
+ if (!init(&new_table, t->t.size_lg2 + 1, a)) {
652
+ return false;
653
+ }
654
+
655
+ for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
656
+ const upb_tabent* e = &t->t.entries[i];
657
+ uint32_t hash;
658
+ upb_value v;
659
+
660
+ _upb_value_setval(&v, e->val.val);
661
+ hash = upb_inthash(e->key);
662
+ insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
663
+ }
664
+
665
+ UPB_ASSERT(t->t.count == new_table.count);
666
+
667
+ t->t = new_table;
668
+ }
669
+ insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
670
+ }
671
+ check(t);
672
+ return true;
673
+ }
674
+
675
+ bool upb_inttable_lookup(const upb_inttable* t, uintptr_t key, upb_value* v) {
676
+ const upb_tabval* table_v = inttable_val_const(t, key);
677
+ if (!table_v) return false;
678
+ if (v) _upb_value_setval(v, table_v->val);
679
+ return true;
680
+ }
681
+
682
+ bool upb_inttable_replace(upb_inttable* t, uintptr_t key, upb_value val) {
683
+ upb_tabval* table_v = inttable_val(t, key);
684
+ if (!table_v) return false;
685
+ table_v->val = val.val;
686
+ return true;
687
+ }
688
+
689
+ bool upb_inttable_remove(upb_inttable* t, uintptr_t key, upb_value* val) {
690
+ bool success;
691
+ if (key < t->array_size) {
692
+ if (upb_arrhas(t->array[key])) {
693
+ upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
694
+ t->array_count--;
695
+ if (val) {
696
+ _upb_value_setval(val, t->array[key].val);
697
+ }
698
+ mutable_array(t)[key] = empty;
699
+ success = true;
700
+ } else {
701
+ success = false;
702
+ }
703
+ } else {
704
+ success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
705
+ }
706
+ check(t);
707
+ return success;
708
+ }
709
+
710
+ void upb_inttable_compact(upb_inttable* t, upb_Arena* a) {
711
+ /* A power-of-two histogram of the table keys. */
712
+ size_t counts[UPB_MAXARRSIZE + 1] = {0};
713
+
714
+ /* The max key in each bucket. */
715
+ uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
716
+
717
+ upb_inttable_iter i;
718
+ size_t arr_count;
719
+ int size_lg2;
720
+ upb_inttable new_t;
721
+
722
+ upb_inttable_begin(&i, t);
723
+ for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
724
+ uintptr_t key = upb_inttable_iter_key(&i);
725
+ int bucket = log2ceil(key);
726
+ max[bucket] = UPB_MAX(max[bucket], key);
727
+ counts[bucket]++;
728
+ }
729
+
730
+ /* Find the largest power of two that satisfies the MIN_DENSITY
731
+ * definition (while actually having some keys). */
732
+ arr_count = upb_inttable_count(t);
733
+
734
+ for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
735
+ if (counts[size_lg2] == 0) {
736
+ /* We can halve again without losing any entries. */
737
+ continue;
738
+ } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
739
+ break;
740
+ }
741
+
742
+ arr_count -= counts[size_lg2];
743
+ }
744
+
745
+ UPB_ASSERT(arr_count <= upb_inttable_count(t));
746
+
747
+ {
748
+ /* Insert all elements into new, perfectly-sized table. */
749
+ size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */
750
+ size_t hash_count = upb_inttable_count(t) - arr_count;
751
+ size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
752
+ int hashsize_lg2 = log2ceil(hash_size);
753
+
754
+ upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
755
+ upb_inttable_begin(&i, t);
756
+ for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
757
+ uintptr_t k = upb_inttable_iter_key(&i);
758
+ upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i), a);
759
+ }
760
+ UPB_ASSERT(new_t.array_size == arr_size);
761
+ UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
762
+ }
763
+ *t = new_t;
764
+ }
765
+
766
+ /* Iteration. */
767
+
768
+ static const upb_tabent* int_tabent(const upb_inttable_iter* i) {
769
+ UPB_ASSERT(!i->array_part);
770
+ return &i->t->t.entries[i->index];
771
+ }
772
+
773
+ static upb_tabval int_arrent(const upb_inttable_iter* i) {
774
+ UPB_ASSERT(i->array_part);
775
+ return i->t->array[i->index];
776
+ }
777
+
778
+ void upb_inttable_begin(upb_inttable_iter* i, const upb_inttable* t) {
779
+ i->t = t;
780
+ i->index = -1;
781
+ i->array_part = true;
782
+ upb_inttable_next(i);
783
+ }
784
+
785
+ void upb_inttable_next(upb_inttable_iter* iter) {
786
+ const upb_inttable* t = iter->t;
787
+ if (iter->array_part) {
788
+ while (++iter->index < t->array_size) {
789
+ if (upb_arrhas(int_arrent(iter))) {
790
+ return;
791
+ }
792
+ }
793
+ iter->array_part = false;
794
+ iter->index = begin(&t->t);
795
+ } else {
796
+ iter->index = next(&t->t, iter->index);
797
+ }
798
+ }
799
+
800
+ bool upb_inttable_next2(const upb_inttable* t, uintptr_t* key, upb_value* val,
801
+ intptr_t* iter) {
802
+ intptr_t i = *iter;
803
+ if (i < t->array_size) {
804
+ while (++i < t->array_size) {
805
+ upb_tabval ent = t->array[i];
806
+ if (upb_arrhas(ent)) {
807
+ *key = i;
808
+ *val = _upb_value_val(ent.val);
809
+ *iter = i;
810
+ return true;
811
+ }
812
+ }
813
+ }
814
+
815
+ size_t tab_idx = next(&t->t, i == -1 ? -1 : i - t->array_size);
816
+ if (tab_idx < upb_table_size(&t->t)) {
817
+ upb_tabent* ent = &t->t.entries[tab_idx];
818
+ *key = ent->key;
819
+ *val = _upb_value_val(ent->val.val);
820
+ *iter = tab_idx + t->array_size;
821
+ return true;
822
+ }
823
+
824
+ return false;
825
+ }
826
+
827
+ void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter) {
828
+ intptr_t i = *iter;
829
+ if (i < t->array_size) {
830
+ t->array_count--;
831
+ mutable_array(t)[i].val = -1;
832
+ } else {
833
+ upb_tabent* ent = &t->t.entries[i - t->array_size];
834
+ upb_tabent* prev = NULL;
835
+
836
+ // Linear search, not great.
837
+ upb_tabent* end = &t->t.entries[upb_table_size(&t->t)];
838
+ for (upb_tabent* e = t->t.entries; e != end; e++) {
839
+ if (e->next == ent) {
840
+ prev = e;
841
+ break;
842
+ }
843
+ }
844
+
845
+ if (prev) {
846
+ prev->next = ent->next;
847
+ }
848
+
849
+ t->t.count--;
850
+ ent->key = 0;
851
+ ent->next = NULL;
852
+ }
853
+ }
854
+
855
+ bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key,
856
+ upb_value* val, intptr_t* iter) {
857
+ size_t tab_idx = next(&t->t, *iter);
858
+ if (tab_idx < upb_table_size(&t->t)) {
859
+ upb_tabent* ent = &t->t.entries[tab_idx];
860
+ uint32_t len;
861
+ key->data = upb_tabstr(ent->key, &len);
862
+ key->size = len;
863
+ *val = _upb_value_val(ent->val.val);
864
+ *iter = tab_idx;
865
+ return true;
866
+ }
867
+
868
+ return false;
869
+ }
870
+
871
+ void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter) {
872
+ intptr_t i = *iter;
873
+ upb_tabent* ent = &t->t.entries[i];
874
+ upb_tabent* prev = NULL;
875
+
876
+ // Linear search, not great.
877
+ upb_tabent* end = &t->t.entries[upb_table_size(&t->t)];
878
+ for (upb_tabent* e = t->t.entries; e != end; e++) {
879
+ if (e->next == ent) {
880
+ prev = e;
881
+ break;
882
+ }
883
+ }
884
+
885
+ if (prev) {
886
+ prev->next = ent->next;
887
+ }
888
+
889
+ t->t.count--;
890
+ ent->key = 0;
891
+ ent->next = NULL;
892
+ }
893
+
894
+ bool upb_inttable_done(const upb_inttable_iter* i) {
895
+ if (!i->t) return true;
896
+ if (i->array_part) {
897
+ return i->index >= i->t->array_size || !upb_arrhas(int_arrent(i));
898
+ } else {
899
+ return i->index >= upb_table_size(&i->t->t) ||
900
+ upb_tabent_isempty(int_tabent(i));
901
+ }
902
+ }
903
+
904
+ uintptr_t upb_inttable_iter_key(const upb_inttable_iter* i) {
905
+ UPB_ASSERT(!upb_inttable_done(i));
906
+ return i->array_part ? i->index : int_tabent(i)->key;
907
+ }
908
+
909
+ upb_value upb_inttable_iter_value(const upb_inttable_iter* i) {
910
+ UPB_ASSERT(!upb_inttable_done(i));
911
+ return _upb_value_val(i->array_part ? i->t->array[i->index].val
912
+ : int_tabent(i)->val.val);
913
+ }
914
+
915
+ void upb_inttable_iter_setdone(upb_inttable_iter* i) {
916
+ i->t = NULL;
917
+ i->index = SIZE_MAX;
918
+ i->array_part = false;
919
+ }
920
+
921
+ bool upb_inttable_iter_isequal(const upb_inttable_iter* i1,
922
+ const upb_inttable_iter* i2) {
923
+ if (upb_inttable_done(i1) && upb_inttable_done(i2)) return true;
924
+ return i1->t == i2->t && i1->index == i2->index &&
925
+ i1->array_part == i2->array_part;
926
+ }