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,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 */