ruby_memprofiler_pprof 0.0.1

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 (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,1055 @@
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
+ // Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64.
29
+ // Also the table size grows by 2x.
30
+ //
31
+ // Could potentially be ported to other 64-bit archs that pass at least six
32
+ // arguments in registers and have 8 unused high bits in pointers.
33
+ //
34
+ // The overall design is to create specialized functions for every possible
35
+ // field type (eg. oneof boolean field with a 1 byte tag) and then dispatch
36
+ // to the specialized function as quickly as possible.
37
+
38
+ #include "upb/decode_fast.h"
39
+
40
+ #include "upb/decode_internal.h"
41
+
42
+ /* Must be last. */
43
+ #include "upb/port_def.inc"
44
+
45
+ #if UPB_FASTTABLE
46
+
47
+ // The standard set of arguments passed to each parsing function.
48
+ // Thanks to x86-64 calling conventions, these will stay in registers.
49
+ #define UPB_PARSE_PARAMS \
50
+ upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \
51
+ uint64_t hasbits, uint64_t data
52
+
53
+ #define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
54
+
55
+ #define RETURN_GENERIC(m) \
56
+ /* Uncomment either of these for debugging purposes. */ \
57
+ /* fprintf(stderr, m); */ \
58
+ /*__builtin_trap(); */ \
59
+ return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
60
+
61
+ typedef enum {
62
+ CARD_s = 0, /* Singular (optional, non-repeated) */
63
+ CARD_o = 1, /* Oneof */
64
+ CARD_r = 2, /* Repeated */
65
+ CARD_p = 3 /* Packed Repeated */
66
+ } upb_card;
67
+
68
+ UPB_NOINLINE
69
+ static const char* fastdecode_isdonefallback(UPB_PARSE_PARAMS) {
70
+ int overrun = data;
71
+ int status;
72
+ ptr = decode_isdonefallback_inl(d, ptr, overrun, &status);
73
+ if (ptr == NULL) {
74
+ return fastdecode_err(d, status);
75
+ }
76
+ data = fastdecode_loadtag(ptr);
77
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
78
+ }
79
+
80
+ UPB_FORCEINLINE
81
+ static const char* fastdecode_dispatch(UPB_PARSE_PARAMS) {
82
+ if (UPB_UNLIKELY(ptr >= d->limit_ptr)) {
83
+ int overrun = ptr - d->end;
84
+ if (UPB_LIKELY(overrun == d->limit)) {
85
+ // Parse is finished.
86
+ *(uint32_t*)msg |= hasbits; // Sync hasbits.
87
+ const upb_MiniTable* l = decode_totablep(table);
88
+ return UPB_UNLIKELY(l->required_count)
89
+ ? decode_checkrequired(d, ptr, msg, l)
90
+ : ptr;
91
+ } else {
92
+ data = overrun;
93
+ UPB_MUSTTAIL return fastdecode_isdonefallback(UPB_PARSE_ARGS);
94
+ }
95
+ }
96
+
97
+ // Read two bytes of tag data (for a one-byte tag, the high byte is junk).
98
+ data = fastdecode_loadtag(ptr);
99
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
100
+ }
101
+
102
+ UPB_FORCEINLINE
103
+ static bool fastdecode_checktag(uint16_t data, int tagbytes) {
104
+ if (tagbytes == 1) {
105
+ return (data & 0xff) == 0;
106
+ } else {
107
+ return data == 0;
108
+ }
109
+ }
110
+
111
+ UPB_FORCEINLINE
112
+ static const char* fastdecode_longsize(const char* ptr, int* size) {
113
+ int i;
114
+ UPB_ASSERT(*size & 0x80);
115
+ *size &= 0xff;
116
+ for (i = 0; i < 3; i++) {
117
+ ptr++;
118
+ size_t byte = (uint8_t)ptr[-1];
119
+ *size += (byte - 1) << (7 + 7 * i);
120
+ if (UPB_LIKELY((byte & 0x80) == 0)) return ptr;
121
+ }
122
+ ptr++;
123
+ size_t byte = (uint8_t)ptr[-1];
124
+ // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected
125
+ // for a 32 bit varint.
126
+ if (UPB_UNLIKELY(byte >= 8)) return NULL;
127
+ *size += (byte - 1) << 28;
128
+ return ptr;
129
+ }
130
+
131
+ UPB_FORCEINLINE
132
+ static bool fastdecode_boundscheck(const char* ptr, size_t len,
133
+ const char* end) {
134
+ uintptr_t uptr = (uintptr_t)ptr;
135
+ uintptr_t uend = (uintptr_t)end + 16;
136
+ uintptr_t res = uptr + len;
137
+ return res < uptr || res > uend;
138
+ }
139
+
140
+ UPB_FORCEINLINE
141
+ static bool fastdecode_boundscheck2(const char* ptr, size_t len,
142
+ const char* end) {
143
+ // This is one extra branch compared to the more normal:
144
+ // return (size_t)(end - ptr) < size;
145
+ // However it is one less computation if we are just about to use "ptr + len":
146
+ // https://godbolt.org/z/35YGPz
147
+ // In microbenchmarks this shows an overall 4% improvement.
148
+ uintptr_t uptr = (uintptr_t)ptr;
149
+ uintptr_t uend = (uintptr_t)end;
150
+ uintptr_t res = uptr + len;
151
+ return res < uptr || res > uend;
152
+ }
153
+
154
+ typedef const char* fastdecode_delimfunc(upb_Decoder* d, const char* ptr,
155
+ void* ctx);
156
+
157
+ UPB_FORCEINLINE
158
+ static const char* fastdecode_delimited(upb_Decoder* d, const char* ptr,
159
+ fastdecode_delimfunc* func, void* ctx) {
160
+ ptr++;
161
+ int len = (int8_t)ptr[-1];
162
+ if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) {
163
+ // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer.
164
+ // If it exceeds the buffer limit, limit/limit_ptr will change during
165
+ // sub-message parsing, so we need to preserve delta, not limit.
166
+ if (UPB_UNLIKELY(len & 0x80)) {
167
+ // Size varint >1 byte (length >= 128).
168
+ ptr = fastdecode_longsize(ptr, &len);
169
+ if (!ptr) {
170
+ // Corrupt wire format: size exceeded INT_MAX.
171
+ return NULL;
172
+ }
173
+ }
174
+ if (ptr - d->end + (int)len > d->limit) {
175
+ // Corrupt wire format: invalid limit.
176
+ return NULL;
177
+ }
178
+ int delta = decode_pushlimit(d, ptr, len);
179
+ ptr = func(d, ptr, ctx);
180
+ decode_poplimit(d, ptr, delta);
181
+ } else {
182
+ // Fast case: Sub-message is <128 bytes and fits in the current buffer.
183
+ // This means we can preserve limit/limit_ptr verbatim.
184
+ const char* saved_limit_ptr = d->limit_ptr;
185
+ int saved_limit = d->limit;
186
+ d->limit_ptr = ptr + len;
187
+ d->limit = d->limit_ptr - d->end;
188
+ UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
189
+ ptr = func(d, ptr, ctx);
190
+ d->limit_ptr = saved_limit_ptr;
191
+ d->limit = saved_limit;
192
+ UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
193
+ }
194
+ return ptr;
195
+ }
196
+
197
+ /* singular, oneof, repeated field handling ***********************************/
198
+
199
+ typedef struct {
200
+ upb_Array* arr;
201
+ void* end;
202
+ } fastdecode_arr;
203
+
204
+ typedef enum {
205
+ FD_NEXT_ATLIMIT,
206
+ FD_NEXT_SAMEFIELD,
207
+ FD_NEXT_OTHERFIELD
208
+ } fastdecode_next;
209
+
210
+ typedef struct {
211
+ void* dst;
212
+ fastdecode_next next;
213
+ uint32_t tag;
214
+ } fastdecode_nextret;
215
+
216
+ UPB_FORCEINLINE
217
+ static void* fastdecode_resizearr(upb_Decoder* d, void* dst,
218
+ fastdecode_arr* farr, int valbytes) {
219
+ if (UPB_UNLIKELY(dst == farr->end)) {
220
+ size_t old_size = farr->arr->size;
221
+ size_t old_bytes = old_size * valbytes;
222
+ size_t new_size = old_size * 2;
223
+ size_t new_bytes = new_size * valbytes;
224
+ char* old_ptr = _upb_array_ptr(farr->arr);
225
+ char* new_ptr = upb_Arena_Realloc(&d->arena, old_ptr, old_bytes, new_bytes);
226
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
227
+ farr->arr->size = new_size;
228
+ farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2);
229
+ dst = (void*)(new_ptr + (old_size * valbytes));
230
+ farr->end = (void*)(new_ptr + (new_size * valbytes));
231
+ }
232
+ return dst;
233
+ }
234
+
235
+ UPB_FORCEINLINE
236
+ static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) {
237
+ if (tagbytes == 1) {
238
+ return (uint8_t)tag == (uint8_t)data;
239
+ } else {
240
+ return (uint16_t)tag == (uint16_t)data;
241
+ }
242
+ }
243
+
244
+ UPB_FORCEINLINE
245
+ static void fastdecode_commitarr(void* dst, fastdecode_arr* farr,
246
+ int valbytes) {
247
+ farr->arr->len =
248
+ (size_t)((char*)dst - (char*)_upb_array_ptr(farr->arr)) / valbytes;
249
+ }
250
+
251
+ UPB_FORCEINLINE
252
+ static fastdecode_nextret fastdecode_nextrepeated(upb_Decoder* d, void* dst,
253
+ const char** ptr,
254
+ fastdecode_arr* farr,
255
+ uint64_t data, int tagbytes,
256
+ int valbytes) {
257
+ fastdecode_nextret ret;
258
+ dst = (char*)dst + valbytes;
259
+
260
+ if (UPB_LIKELY(!decode_isdone(d, ptr))) {
261
+ ret.tag = fastdecode_loadtag(*ptr);
262
+ if (fastdecode_tagmatch(ret.tag, data, tagbytes)) {
263
+ ret.next = FD_NEXT_SAMEFIELD;
264
+ } else {
265
+ fastdecode_commitarr(dst, farr, valbytes);
266
+ ret.next = FD_NEXT_OTHERFIELD;
267
+ }
268
+ } else {
269
+ fastdecode_commitarr(dst, farr, valbytes);
270
+ ret.next = FD_NEXT_ATLIMIT;
271
+ }
272
+
273
+ ret.dst = dst;
274
+ return ret;
275
+ }
276
+
277
+ UPB_FORCEINLINE
278
+ static void* fastdecode_fieldmem(upb_Message* msg, uint64_t data) {
279
+ size_t ofs = data >> 48;
280
+ return (char*)msg + ofs;
281
+ }
282
+
283
+ UPB_FORCEINLINE
284
+ static void* fastdecode_getfield(upb_Decoder* d, const char* ptr,
285
+ upb_Message* msg, uint64_t* data,
286
+ uint64_t* hasbits, fastdecode_arr* farr,
287
+ int valbytes, upb_card card) {
288
+ switch (card) {
289
+ case CARD_s: {
290
+ uint8_t hasbit_index = *data >> 24;
291
+ // Set hasbit and return pointer to scalar field.
292
+ *hasbits |= 1ull << hasbit_index;
293
+ return fastdecode_fieldmem(msg, *data);
294
+ }
295
+ case CARD_o: {
296
+ uint16_t case_ofs = *data >> 32;
297
+ uint32_t* oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t);
298
+ uint8_t field_number = *data >> 24;
299
+ *oneof_case = field_number;
300
+ return fastdecode_fieldmem(msg, *data);
301
+ }
302
+ case CARD_r: {
303
+ // Get pointer to upb_Array and allocate/expand if necessary.
304
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
305
+ upb_Array** arr_p = fastdecode_fieldmem(msg, *data);
306
+ char* begin;
307
+ *(uint32_t*)msg |= *hasbits;
308
+ *hasbits = 0;
309
+ if (UPB_LIKELY(!*arr_p)) {
310
+ farr->arr = _upb_Array_New(&d->arena, 8, elem_size_lg2);
311
+ *arr_p = farr->arr;
312
+ } else {
313
+ farr->arr = *arr_p;
314
+ }
315
+ begin = _upb_array_ptr(farr->arr);
316
+ farr->end = begin + (farr->arr->size * valbytes);
317
+ *data = fastdecode_loadtag(ptr);
318
+ return begin + (farr->arr->len * valbytes);
319
+ }
320
+ default:
321
+ UPB_UNREACHABLE();
322
+ }
323
+ }
324
+
325
+ UPB_FORCEINLINE
326
+ static bool fastdecode_flippacked(uint64_t* data, int tagbytes) {
327
+ *data ^= (0x2 ^ 0x0); // Patch data to match packed wiretype.
328
+ return fastdecode_checktag(*data, tagbytes);
329
+ }
330
+
331
+ #define FASTDECODE_CHECKPACKED(tagbytes, card, func) \
332
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
333
+ if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { \
334
+ UPB_MUSTTAIL return func(UPB_PARSE_ARGS); \
335
+ } \
336
+ RETURN_GENERIC("packed check tag mismatch\n"); \
337
+ }
338
+
339
+ /* varint fields **************************************************************/
340
+
341
+ UPB_FORCEINLINE
342
+ static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) {
343
+ if (valbytes == 1) {
344
+ return val != 0;
345
+ } else if (zigzag) {
346
+ if (valbytes == 4) {
347
+ uint32_t n = val;
348
+ return (n >> 1) ^ -(int32_t)(n & 1);
349
+ } else if (valbytes == 8) {
350
+ return (val >> 1) ^ -(int64_t)(val & 1);
351
+ }
352
+ UPB_UNREACHABLE();
353
+ }
354
+ return val;
355
+ }
356
+
357
+ UPB_FORCEINLINE
358
+ static const char* fastdecode_varint64(const char* ptr, uint64_t* val) {
359
+ ptr++;
360
+ *val = (uint8_t)ptr[-1];
361
+ if (UPB_UNLIKELY(*val & 0x80)) {
362
+ int i;
363
+ for (i = 0; i < 8; i++) {
364
+ ptr++;
365
+ uint64_t byte = (uint8_t)ptr[-1];
366
+ *val += (byte - 1) << (7 + 7 * i);
367
+ if (UPB_LIKELY((byte & 0x80) == 0)) goto done;
368
+ }
369
+ ptr++;
370
+ uint64_t byte = (uint8_t)ptr[-1];
371
+ if (byte > 1) {
372
+ return NULL;
373
+ }
374
+ *val += (byte - 1) << 63;
375
+ }
376
+ done:
377
+ UPB_ASSUME(ptr != NULL);
378
+ return ptr;
379
+ }
380
+
381
+ #define FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
382
+ valbytes, card, zigzag, packed) \
383
+ uint64_t val; \
384
+ void* dst; \
385
+ fastdecode_arr farr; \
386
+ \
387
+ FASTDECODE_CHECKPACKED(tagbytes, card, packed); \
388
+ \
389
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, \
390
+ card); \
391
+ if (card == CARD_r) { \
392
+ if (UPB_UNLIKELY(!dst)) { \
393
+ RETURN_GENERIC("need array resize\n"); \
394
+ } \
395
+ } \
396
+ \
397
+ again: \
398
+ if (card == CARD_r) { \
399
+ dst = fastdecode_resizearr(d, dst, &farr, valbytes); \
400
+ } \
401
+ \
402
+ ptr += tagbytes; \
403
+ ptr = fastdecode_varint64(ptr, &val); \
404
+ if (ptr == NULL) return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
405
+ val = fastdecode_munge(val, valbytes, zigzag); \
406
+ memcpy(dst, &val, valbytes); \
407
+ \
408
+ if (card == CARD_r) { \
409
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
410
+ d, dst, &ptr, &farr, data, tagbytes, valbytes); \
411
+ switch (ret.next) { \
412
+ case FD_NEXT_SAMEFIELD: \
413
+ dst = ret.dst; \
414
+ goto again; \
415
+ case FD_NEXT_OTHERFIELD: \
416
+ data = ret.tag; \
417
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
418
+ case FD_NEXT_ATLIMIT: \
419
+ return ptr; \
420
+ } \
421
+ } \
422
+ \
423
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
424
+
425
+ typedef struct {
426
+ uint8_t valbytes;
427
+ bool zigzag;
428
+ void* dst;
429
+ fastdecode_arr farr;
430
+ } fastdecode_varintdata;
431
+
432
+ UPB_FORCEINLINE
433
+ static const char* fastdecode_topackedvarint(upb_Decoder* d, const char* ptr,
434
+ void* ctx) {
435
+ fastdecode_varintdata* data = ctx;
436
+ void* dst = data->dst;
437
+ uint64_t val;
438
+
439
+ while (!decode_isdone(d, &ptr)) {
440
+ dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes);
441
+ ptr = fastdecode_varint64(ptr, &val);
442
+ if (ptr == NULL) return NULL;
443
+ val = fastdecode_munge(val, data->valbytes, data->zigzag);
444
+ memcpy(dst, &val, data->valbytes);
445
+ dst = (char*)dst + data->valbytes;
446
+ }
447
+
448
+ fastdecode_commitarr(dst, &data->farr, data->valbytes);
449
+ return ptr;
450
+ }
451
+
452
+ #define FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
453
+ valbytes, zigzag, unpacked) \
454
+ fastdecode_varintdata ctx = {valbytes, zigzag}; \
455
+ \
456
+ FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked); \
457
+ \
458
+ ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr, \
459
+ valbytes, CARD_r); \
460
+ if (UPB_UNLIKELY(!ctx.dst)) { \
461
+ RETURN_GENERIC("need array resize\n"); \
462
+ } \
463
+ \
464
+ ptr += tagbytes; \
465
+ ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx); \
466
+ \
467
+ if (UPB_UNLIKELY(ptr == NULL)) { \
468
+ return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
469
+ } \
470
+ \
471
+ UPB_MUSTTAIL return fastdecode_dispatch(d, ptr, msg, table, hasbits, 0);
472
+
473
+ #define FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
474
+ valbytes, card, zigzag, unpacked, packed) \
475
+ if (card == CARD_p) { \
476
+ FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
477
+ valbytes, zigzag, unpacked); \
478
+ } else { \
479
+ FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
480
+ valbytes, card, zigzag, packed); \
481
+ }
482
+
483
+ #define z_ZZ true
484
+ #define b_ZZ false
485
+ #define v_ZZ false
486
+
487
+ /* Generate all combinations:
488
+ * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */
489
+
490
+ #define F(card, type, valbytes, tagbytes) \
491
+ UPB_NOINLINE \
492
+ const char* upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
493
+ FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
494
+ CARD_##card, type##_ZZ, \
495
+ upb_pr##type##valbytes##_##tagbytes##bt, \
496
+ upb_pp##type##valbytes##_##tagbytes##bt); \
497
+ }
498
+
499
+ #define TYPES(card, tagbytes) \
500
+ F(card, b, 1, tagbytes) \
501
+ F(card, v, 4, tagbytes) \
502
+ F(card, v, 8, tagbytes) \
503
+ F(card, z, 4, tagbytes) \
504
+ F(card, z, 8, tagbytes)
505
+
506
+ #define TAGBYTES(card) \
507
+ TYPES(card, 1) \
508
+ TYPES(card, 2)
509
+
510
+ TAGBYTES(s)
511
+ TAGBYTES(o)
512
+ TAGBYTES(r)
513
+ TAGBYTES(p)
514
+
515
+ #undef z_ZZ
516
+ #undef b_ZZ
517
+ #undef v_ZZ
518
+ #undef o_ONEOF
519
+ #undef s_ONEOF
520
+ #undef r_ONEOF
521
+ #undef F
522
+ #undef TYPES
523
+ #undef TAGBYTES
524
+ #undef FASTDECODE_UNPACKEDVARINT
525
+ #undef FASTDECODE_PACKEDVARINT
526
+ #undef FASTDECODE_VARINT
527
+
528
+ /* fixed fields ***************************************************************/
529
+
530
+ #define FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
531
+ valbytes, card, packed) \
532
+ void* dst; \
533
+ fastdecode_arr farr; \
534
+ \
535
+ FASTDECODE_CHECKPACKED(tagbytes, card, packed) \
536
+ \
537
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, \
538
+ card); \
539
+ if (card == CARD_r) { \
540
+ if (UPB_UNLIKELY(!dst)) { \
541
+ RETURN_GENERIC("couldn't allocate array in arena\n"); \
542
+ } \
543
+ } \
544
+ \
545
+ again: \
546
+ if (card == CARD_r) { \
547
+ dst = fastdecode_resizearr(d, dst, &farr, valbytes); \
548
+ } \
549
+ \
550
+ ptr += tagbytes; \
551
+ memcpy(dst, ptr, valbytes); \
552
+ ptr += valbytes; \
553
+ \
554
+ if (card == CARD_r) { \
555
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
556
+ d, dst, &ptr, &farr, data, tagbytes, valbytes); \
557
+ switch (ret.next) { \
558
+ case FD_NEXT_SAMEFIELD: \
559
+ dst = ret.dst; \
560
+ goto again; \
561
+ case FD_NEXT_OTHERFIELD: \
562
+ data = ret.tag; \
563
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
564
+ case FD_NEXT_ATLIMIT: \
565
+ return ptr; \
566
+ } \
567
+ } \
568
+ \
569
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
570
+
571
+ #define FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
572
+ valbytes, unpacked) \
573
+ FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked) \
574
+ \
575
+ ptr += tagbytes; \
576
+ int size = (uint8_t)ptr[0]; \
577
+ ptr++; \
578
+ if (size & 0x80) { \
579
+ ptr = fastdecode_longsize(ptr, &size); \
580
+ } \
581
+ \
582
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr) || \
583
+ (size % valbytes) != 0)) { \
584
+ return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
585
+ } \
586
+ \
587
+ upb_Array** arr_p = fastdecode_fieldmem(msg, data); \
588
+ upb_Array* arr = *arr_p; \
589
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes); \
590
+ int elems = size / valbytes; \
591
+ \
592
+ if (UPB_LIKELY(!arr)) { \
593
+ *arr_p = arr = _upb_Array_New(&d->arena, elems, elem_size_lg2); \
594
+ if (!arr) { \
595
+ return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
596
+ } \
597
+ } else { \
598
+ _upb_Array_Resize(arr, elems, &d->arena); \
599
+ } \
600
+ \
601
+ char* dst = _upb_array_ptr(arr); \
602
+ memcpy(dst, ptr, size); \
603
+ arr->len = elems; \
604
+ \
605
+ ptr += size; \
606
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
607
+
608
+ #define FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
609
+ valbytes, card, unpacked, packed) \
610
+ if (card == CARD_p) { \
611
+ FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
612
+ valbytes, unpacked); \
613
+ } else { \
614
+ FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
615
+ valbytes, card, packed); \
616
+ }
617
+
618
+ /* Generate all combinations:
619
+ * {s,o,r,p} x {f4,f8} x {1bt,2bt} */
620
+
621
+ #define F(card, valbytes, tagbytes) \
622
+ UPB_NOINLINE \
623
+ const char* upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
624
+ FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
625
+ CARD_##card, upb_ppf##valbytes##_##tagbytes##bt, \
626
+ upb_prf##valbytes##_##tagbytes##bt); \
627
+ }
628
+
629
+ #define TYPES(card, tagbytes) \
630
+ F(card, 4, tagbytes) \
631
+ F(card, 8, tagbytes)
632
+
633
+ #define TAGBYTES(card) \
634
+ TYPES(card, 1) \
635
+ TYPES(card, 2)
636
+
637
+ TAGBYTES(s)
638
+ TAGBYTES(o)
639
+ TAGBYTES(r)
640
+ TAGBYTES(p)
641
+
642
+ #undef F
643
+ #undef TYPES
644
+ #undef TAGBYTES
645
+ #undef FASTDECODE_UNPACKEDFIXED
646
+ #undef FASTDECODE_PACKEDFIXED
647
+
648
+ /* string fields **************************************************************/
649
+
650
+ typedef const char* fastdecode_copystr_func(struct upb_Decoder* d,
651
+ const char* ptr, upb_Message* msg,
652
+ const upb_MiniTable* table,
653
+ uint64_t hasbits,
654
+ upb_StringView* dst);
655
+
656
+ UPB_NOINLINE
657
+ static const char* fastdecode_verifyutf8(upb_Decoder* d, const char* ptr,
658
+ upb_Message* msg, intptr_t table,
659
+ uint64_t hasbits, uint64_t data) {
660
+ upb_StringView* dst = (upb_StringView*)data;
661
+ if (!decode_verifyutf8_inl(dst->data, dst->size)) {
662
+ return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8);
663
+ }
664
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
665
+ }
666
+
667
+ #define FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, validate_utf8) \
668
+ int size = (uint8_t)ptr[0]; /* Could plumb through hasbits. */ \
669
+ ptr++; \
670
+ if (size & 0x80) { \
671
+ ptr = fastdecode_longsize(ptr, &size); \
672
+ } \
673
+ \
674
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) { \
675
+ dst->size = 0; \
676
+ return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
677
+ } \
678
+ \
679
+ if (d->options & kUpb_DecodeOption_AliasString) { \
680
+ dst->data = ptr; \
681
+ dst->size = size; \
682
+ } else { \
683
+ char* data = upb_Arena_Malloc(&d->arena, size); \
684
+ if (!data) { \
685
+ return fastdecode_err(d, kUpb_DecodeStatus_OutOfMemory); \
686
+ } \
687
+ memcpy(data, ptr, size); \
688
+ dst->data = data; \
689
+ dst->size = size; \
690
+ } \
691
+ \
692
+ ptr += size; \
693
+ if (validate_utf8) { \
694
+ data = (uint64_t)dst; \
695
+ UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
696
+ } else { \
697
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); \
698
+ }
699
+
700
+ UPB_NOINLINE
701
+ static const char* fastdecode_longstring_utf8(struct upb_Decoder* d,
702
+ const char* ptr, upb_Message* msg,
703
+ intptr_t table, uint64_t hasbits,
704
+ uint64_t data) {
705
+ upb_StringView* dst = (upb_StringView*)data;
706
+ FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
707
+ }
708
+
709
+ UPB_NOINLINE
710
+ static const char* fastdecode_longstring_noutf8(
711
+ struct upb_Decoder* d, const char* ptr, upb_Message* msg, intptr_t table,
712
+ uint64_t hasbits, uint64_t data) {
713
+ upb_StringView* dst = (upb_StringView*)data;
714
+ FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
715
+ }
716
+
717
+ UPB_FORCEINLINE
718
+ static void fastdecode_docopy(upb_Decoder* d, const char* ptr, uint32_t size,
719
+ int copy, char* data, upb_StringView* dst) {
720
+ d->arena.head.ptr += copy;
721
+ dst->data = data;
722
+ UPB_UNPOISON_MEMORY_REGION(data, copy);
723
+ memcpy(data, ptr, copy);
724
+ UPB_POISON_MEMORY_REGION(data + size, copy - size);
725
+ }
726
+
727
+ #define FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
728
+ card, validate_utf8) \
729
+ upb_StringView* dst; \
730
+ fastdecode_arr farr; \
731
+ int64_t size; \
732
+ size_t arena_has; \
733
+ size_t common_has; \
734
+ char* buf; \
735
+ \
736
+ UPB_ASSERT((d->options & kUpb_DecodeOption_AliasString) == 0); \
737
+ UPB_ASSERT(fastdecode_checktag(data, tagbytes)); \
738
+ \
739
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
740
+ sizeof(upb_StringView), card); \
741
+ \
742
+ again: \
743
+ if (card == CARD_r) { \
744
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView)); \
745
+ } \
746
+ \
747
+ size = (uint8_t)ptr[tagbytes]; \
748
+ ptr += tagbytes + 1; \
749
+ dst->size = size; \
750
+ \
751
+ buf = d->arena.head.ptr; \
752
+ arena_has = _upb_ArenaHas(&d->arena); \
753
+ common_has = UPB_MIN(arena_has, (d->end - ptr) + 16); \
754
+ \
755
+ if (UPB_LIKELY(size <= 15 - tagbytes)) { \
756
+ if (arena_has < 16) goto longstr; \
757
+ d->arena.head.ptr += 16; \
758
+ memcpy(buf, ptr - tagbytes - 1, 16); \
759
+ dst->data = buf + tagbytes + 1; \
760
+ } else if (UPB_LIKELY(size <= 32)) { \
761
+ if (UPB_UNLIKELY(common_has < 32)) goto longstr; \
762
+ fastdecode_docopy(d, ptr, size, 32, buf, dst); \
763
+ } else if (UPB_LIKELY(size <= 64)) { \
764
+ if (UPB_UNLIKELY(common_has < 64)) goto longstr; \
765
+ fastdecode_docopy(d, ptr, size, 64, buf, dst); \
766
+ } else if (UPB_LIKELY(size < 128)) { \
767
+ if (UPB_UNLIKELY(common_has < 128)) goto longstr; \
768
+ fastdecode_docopy(d, ptr, size, 128, buf, dst); \
769
+ } else { \
770
+ goto longstr; \
771
+ } \
772
+ \
773
+ ptr += size; \
774
+ \
775
+ if (card == CARD_r) { \
776
+ if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { \
777
+ return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8); \
778
+ } \
779
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
780
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView)); \
781
+ switch (ret.next) { \
782
+ case FD_NEXT_SAMEFIELD: \
783
+ dst = ret.dst; \
784
+ goto again; \
785
+ case FD_NEXT_OTHERFIELD: \
786
+ data = ret.tag; \
787
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
788
+ case FD_NEXT_ATLIMIT: \
789
+ return ptr; \
790
+ } \
791
+ } \
792
+ \
793
+ if (card != CARD_r && validate_utf8) { \
794
+ data = (uint64_t)dst; \
795
+ UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
796
+ } \
797
+ \
798
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); \
799
+ \
800
+ longstr: \
801
+ if (card == CARD_r) { \
802
+ fastdecode_commitarr(dst + 1, &farr, sizeof(upb_StringView)); \
803
+ } \
804
+ ptr--; \
805
+ if (validate_utf8) { \
806
+ UPB_MUSTTAIL return fastdecode_longstring_utf8(d, ptr, msg, table, \
807
+ hasbits, (uint64_t)dst); \
808
+ } else { \
809
+ UPB_MUSTTAIL return fastdecode_longstring_noutf8(d, ptr, msg, table, \
810
+ hasbits, (uint64_t)dst); \
811
+ }
812
+
813
+ #define FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, card, \
814
+ copyfunc, validate_utf8) \
815
+ upb_StringView* dst; \
816
+ fastdecode_arr farr; \
817
+ int64_t size; \
818
+ \
819
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
820
+ RETURN_GENERIC("string field tag mismatch\n"); \
821
+ } \
822
+ \
823
+ if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
824
+ UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS); \
825
+ } \
826
+ \
827
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
828
+ sizeof(upb_StringView), card); \
829
+ \
830
+ again: \
831
+ if (card == CARD_r) { \
832
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView)); \
833
+ } \
834
+ \
835
+ size = (int8_t)ptr[tagbytes]; \
836
+ ptr += tagbytes + 1; \
837
+ dst->data = ptr; \
838
+ dst->size = size; \
839
+ \
840
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) { \
841
+ ptr--; \
842
+ if (validate_utf8) { \
843
+ return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, \
844
+ (uint64_t)dst); \
845
+ } else { \
846
+ return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, \
847
+ (uint64_t)dst); \
848
+ } \
849
+ } \
850
+ \
851
+ ptr += size; \
852
+ \
853
+ if (card == CARD_r) { \
854
+ if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { \
855
+ return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8); \
856
+ } \
857
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
858
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView)); \
859
+ switch (ret.next) { \
860
+ case FD_NEXT_SAMEFIELD: \
861
+ dst = ret.dst; \
862
+ if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
863
+ /* Buffer flipped and we can't alias any more. Bounce to */ \
864
+ /* copyfunc(), but via dispatch since we need to reload table */ \
865
+ /* data also. */ \
866
+ fastdecode_commitarr(dst, &farr, sizeof(upb_StringView)); \
867
+ data = ret.tag; \
868
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
869
+ } \
870
+ goto again; \
871
+ case FD_NEXT_OTHERFIELD: \
872
+ data = ret.tag; \
873
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
874
+ case FD_NEXT_ATLIMIT: \
875
+ return ptr; \
876
+ } \
877
+ } \
878
+ \
879
+ if (card != CARD_r && validate_utf8) { \
880
+ data = (uint64_t)dst; \
881
+ UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
882
+ } \
883
+ \
884
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
885
+
886
+ /* Generate all combinations:
887
+ * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */
888
+
889
+ #define s_VALIDATE true
890
+ #define b_VALIDATE false
891
+
892
+ #define F(card, tagbytes, type) \
893
+ UPB_NOINLINE \
894
+ const char* upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
895
+ FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
896
+ CARD_##card, type##_VALIDATE); \
897
+ } \
898
+ const char* upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
899
+ FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, \
900
+ CARD_##card, upb_c##card##type##_##tagbytes##bt, \
901
+ type##_VALIDATE); \
902
+ }
903
+
904
+ #define UTF8(card, tagbytes) \
905
+ F(card, tagbytes, s) \
906
+ F(card, tagbytes, b)
907
+
908
+ #define TAGBYTES(card) \
909
+ UTF8(card, 1) \
910
+ UTF8(card, 2)
911
+
912
+ TAGBYTES(s)
913
+ TAGBYTES(o)
914
+ TAGBYTES(r)
915
+
916
+ #undef s_VALIDATE
917
+ #undef b_VALIDATE
918
+ #undef F
919
+ #undef TAGBYTES
920
+ #undef FASTDECODE_LONGSTRING
921
+ #undef FASTDECODE_COPYSTRING
922
+ #undef FASTDECODE_STRING
923
+
924
+ /* message fields *************************************************************/
925
+
926
+ UPB_INLINE
927
+ upb_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* l,
928
+ int msg_ceil_bytes) {
929
+ size_t size = l->size + sizeof(upb_Message_Internal);
930
+ char* msg_data;
931
+ if (UPB_LIKELY(msg_ceil_bytes > 0 &&
932
+ _upb_ArenaHas(&d->arena) >= msg_ceil_bytes)) {
933
+ UPB_ASSERT(size <= (size_t)msg_ceil_bytes);
934
+ msg_data = d->arena.head.ptr;
935
+ d->arena.head.ptr += size;
936
+ UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes);
937
+ memset(msg_data, 0, msg_ceil_bytes);
938
+ UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size);
939
+ } else {
940
+ msg_data = (char*)upb_Arena_Malloc(&d->arena, size);
941
+ memset(msg_data, 0, size);
942
+ }
943
+ return msg_data + sizeof(upb_Message_Internal);
944
+ }
945
+
946
+ typedef struct {
947
+ intptr_t table;
948
+ upb_Message* msg;
949
+ } fastdecode_submsgdata;
950
+
951
+ UPB_FORCEINLINE
952
+ static const char* fastdecode_tosubmsg(upb_Decoder* d, const char* ptr,
953
+ void* ctx) {
954
+ fastdecode_submsgdata* submsg = ctx;
955
+ ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0);
956
+ UPB_ASSUME(ptr != NULL);
957
+ return ptr;
958
+ }
959
+
960
+ #define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \
961
+ msg_ceil_bytes, card) \
962
+ \
963
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
964
+ RETURN_GENERIC("submessage field tag mismatch\n"); \
965
+ } \
966
+ \
967
+ if (--d->depth == 0) { \
968
+ return fastdecode_err(d, kUpb_DecodeStatus_MaxDepthExceeded); \
969
+ } \
970
+ \
971
+ upb_Message** dst; \
972
+ uint32_t submsg_idx = (data >> 16) & 0xff; \
973
+ const upb_MiniTable* tablep = decode_totablep(table); \
974
+ const upb_MiniTable* subtablep = tablep->subs[submsg_idx].submsg; \
975
+ fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \
976
+ fastdecode_arr farr; \
977
+ \
978
+ if (subtablep->table_mask == (uint8_t)-1) { \
979
+ RETURN_GENERIC("submessage doesn't have fast tables."); \
980
+ } \
981
+ \
982
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
983
+ sizeof(upb_Message*), card); \
984
+ \
985
+ if (card == CARD_s) { \
986
+ *(uint32_t*)msg |= hasbits; \
987
+ hasbits = 0; \
988
+ } \
989
+ \
990
+ again: \
991
+ if (card == CARD_r) { \
992
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*)); \
993
+ } \
994
+ \
995
+ submsg.msg = *dst; \
996
+ \
997
+ if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \
998
+ *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \
999
+ } \
1000
+ \
1001
+ ptr += tagbytes; \
1002
+ ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \
1003
+ \
1004
+ if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \
1005
+ return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
1006
+ } \
1007
+ \
1008
+ if (card == CARD_r) { \
1009
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
1010
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*)); \
1011
+ switch (ret.next) { \
1012
+ case FD_NEXT_SAMEFIELD: \
1013
+ dst = ret.dst; \
1014
+ goto again; \
1015
+ case FD_NEXT_OTHERFIELD: \
1016
+ d->depth++; \
1017
+ data = ret.tag; \
1018
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
1019
+ case FD_NEXT_ATLIMIT: \
1020
+ d->depth++; \
1021
+ return ptr; \
1022
+ } \
1023
+ } \
1024
+ \
1025
+ d->depth++; \
1026
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
1027
+
1028
+ #define F(card, tagbytes, size_ceil, ceil_arg) \
1029
+ const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \
1030
+ UPB_PARSE_PARAMS) { \
1031
+ FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \
1032
+ CARD_##card); \
1033
+ }
1034
+
1035
+ #define SIZES(card, tagbytes) \
1036
+ F(card, tagbytes, 64, 64) \
1037
+ F(card, tagbytes, 128, 128) \
1038
+ F(card, tagbytes, 192, 192) \
1039
+ F(card, tagbytes, 256, 256) \
1040
+ F(card, tagbytes, max, -1)
1041
+
1042
+ #define TAGBYTES(card) \
1043
+ SIZES(card, 1) \
1044
+ SIZES(card, 2)
1045
+
1046
+ TAGBYTES(s)
1047
+ TAGBYTES(o)
1048
+ TAGBYTES(r)
1049
+
1050
+ #undef TAGBYTES
1051
+ #undef SIZES
1052
+ #undef F
1053
+ #undef FASTDECODE_SUBMSG
1054
+
1055
+ #endif /* UPB_FASTTABLE */