grpc 1.20.0 → 1.21.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +500 -29
  3. data/etc/roots.pem +146 -0
  4. data/include/grpc/grpc_security.h +1 -1
  5. data/include/grpc/impl/codegen/grpc_types.h +10 -7
  6. data/include/grpc/impl/codegen/port_platform.h +11 -1
  7. data/include/grpc/impl/codegen/slice.h +1 -21
  8. data/include/grpc/impl/codegen/status.h +2 -1
  9. data/include/grpc/slice.h +1 -1
  10. data/src/core/ext/filters/client_channel/backup_poller.cc +19 -13
  11. data/src/core/ext/filters/client_channel/backup_poller.h +3 -0
  12. data/src/core/ext/filters/client_channel/channel_connectivity.cc +1 -1
  13. data/src/core/ext/filters/client_channel/client_channel.cc +2084 -1673
  14. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +2 -3
  15. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +4 -0
  16. data/src/core/ext/filters/client_channel/health/health_check_client.cc +54 -49
  17. data/src/core/ext/filters/client_channel/health/health_check_client.h +20 -9
  18. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +1 -2
  19. data/src/core/ext/filters/client_channel/http_connect_handshaker.h +1 -1
  20. data/src/core/ext/filters/client_channel/lb_policy.cc +3 -30
  21. data/src/core/ext/filters/client_channel/lb_policy.h +16 -25
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +106 -81
  23. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +6 -2
  24. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +8 -12
  25. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +2 -2
  26. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +1 -1
  27. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +57 -49
  28. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +47 -41
  29. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +24 -20
  30. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +989 -284
  31. data/src/core/ext/filters/client_channel/lb_policy_factory.h +4 -1
  32. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +105 -2
  33. data/src/core/ext/filters/client_channel/lb_policy_registry.h +9 -2
  34. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +79 -36
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +84 -2
  36. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +3 -0
  37. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +179 -0
  38. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +15 -3
  39. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +80 -4
  40. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +7 -13
  41. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +2 -2
  42. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +39 -0
  43. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +0 -6
  44. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +2 -64
  45. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc +28 -0
  46. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h +29 -0
  47. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +4 -4
  48. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +367 -232
  49. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +55 -76
  50. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +50 -39
  51. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +18 -12
  52. data/src/core/ext/filters/client_channel/service_config.cc +247 -27
  53. data/src/core/ext/filters/client_channel/service_config.h +119 -166
  54. data/src/core/ext/filters/client_channel/subchannel.cc +46 -84
  55. data/src/core/ext/filters/client_channel/subchannel.h +7 -7
  56. data/src/core/ext/filters/deadline/deadline_filter.cc +3 -4
  57. data/src/core/ext/filters/deadline/deadline_filter.h +3 -2
  58. data/src/core/ext/filters/http/client/http_client_filter.cc +7 -5
  59. data/src/core/ext/filters/http/client/http_client_filter.h +1 -1
  60. data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
  61. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +4 -3
  62. data/src/core/ext/filters/http/server/http_server_filter.cc +18 -12
  63. data/src/core/ext/filters/message_size/message_size_filter.cc +118 -76
  64. data/src/core/ext/filters/message_size/message_size_filter.h +33 -0
  65. data/src/core/ext/transport/chttp2/alpn/alpn.h +1 -1
  66. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +9 -7
  67. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +93 -60
  68. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -1
  69. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +4 -3
  70. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +3 -3
  71. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +8 -2
  72. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +2 -2
  73. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +1 -1
  74. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +3 -2
  75. data/src/core/ext/transport/chttp2/transport/internal.h +35 -23
  76. data/src/core/ext/transport/chttp2/transport/parsing.cc +4 -4
  77. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +3 -3
  78. data/src/core/ext/transport/chttp2/transport/writing.cc +61 -27
  79. data/src/core/ext/transport/inproc/inproc_transport.cc +18 -18
  80. data/src/core/lib/channel/channel_args.cc +0 -101
  81. data/src/core/lib/channel/channel_args.h +0 -37
  82. data/src/core/lib/channel/channel_stack.h +9 -5
  83. data/src/core/lib/channel/channelz_registry.cc +1 -1
  84. data/src/core/lib/channel/connected_channel.cc +2 -2
  85. data/src/core/lib/channel/context.h +3 -0
  86. data/src/core/lib/channel/handshaker.cc +4 -4
  87. data/src/core/lib/channel/handshaker.h +1 -1
  88. data/src/core/lib/compression/compression_args.cc +127 -0
  89. data/src/core/lib/compression/compression_args.h +55 -0
  90. data/src/core/lib/debug/trace.cc +13 -7
  91. data/src/core/lib/debug/trace.h +12 -0
  92. data/src/core/lib/gpr/arena.h +13 -9
  93. data/src/core/lib/gpr/env.h +2 -5
  94. data/src/core/lib/gpr/env_linux.cc +6 -1
  95. data/src/core/lib/gpr/env_posix.cc +5 -0
  96. data/src/core/lib/gpr/env_windows.cc +7 -5
  97. data/src/core/lib/gpr/log.cc +9 -13
  98. data/src/core/lib/gpr/string.cc +12 -6
  99. data/src/core/lib/gpr/string.h +4 -2
  100. data/src/core/lib/gpr/time_posix.cc +13 -0
  101. data/src/core/lib/gprpp/arena.cc +103 -0
  102. data/src/core/lib/gprpp/arena.h +121 -0
  103. data/src/core/lib/gprpp/fork.cc +12 -29
  104. data/src/core/lib/gprpp/global_config.h +87 -0
  105. data/src/core/lib/gprpp/global_config_custom.h +29 -0
  106. data/src/core/lib/gprpp/global_config_env.cc +135 -0
  107. data/src/core/lib/gprpp/global_config_env.h +131 -0
  108. data/src/core/lib/gprpp/global_config_generic.h +44 -0
  109. data/src/core/lib/gprpp/map.h +419 -0
  110. data/src/core/lib/gprpp/optional.h +1 -0
  111. data/src/core/lib/gprpp/orphanable.h +2 -2
  112. data/src/core/lib/gprpp/{mutex_lock.h → pair.h} +15 -19
  113. data/src/core/lib/gprpp/ref_counted.h +18 -2
  114. data/src/core/lib/gprpp/sync.h +126 -0
  115. data/src/core/lib/http/parser.cc +1 -1
  116. data/src/core/lib/iomgr/call_combiner.cc +84 -90
  117. data/src/core/lib/iomgr/call_combiner.h +75 -82
  118. data/src/core/lib/iomgr/cfstream_handle.cc +202 -0
  119. data/src/core/lib/iomgr/cfstream_handle.h +82 -0
  120. data/src/core/lib/iomgr/combiner.h +1 -1
  121. data/src/core/lib/iomgr/endpoint_cfstream.cc +375 -0
  122. data/src/core/lib/iomgr/endpoint_cfstream.h +49 -0
  123. data/src/core/lib/iomgr/endpoint_pair_windows.cc +2 -2
  124. data/src/core/lib/iomgr/error.h +23 -0
  125. data/src/core/lib/iomgr/error_cfstream.cc +52 -0
  126. data/src/core/lib/iomgr/error_cfstream.h +31 -0
  127. data/src/core/lib/iomgr/ev_epoll1_linux.cc +34 -27
  128. data/src/core/lib/iomgr/ev_epollex_linux.cc +33 -33
  129. data/src/core/lib/iomgr/ev_poll_posix.cc +7 -7
  130. data/src/core/lib/iomgr/ev_posix.cc +15 -13
  131. data/src/core/lib/iomgr/ev_posix.h +4 -1
  132. data/src/core/lib/iomgr/executor.cc +13 -9
  133. data/src/core/lib/iomgr/fork_posix.cc +0 -1
  134. data/src/core/lib/iomgr/internal_errqueue.cc +1 -1
  135. data/src/core/lib/iomgr/iomgr.cc +6 -5
  136. data/src/core/lib/iomgr/iomgr_custom.cc +3 -0
  137. data/src/core/lib/iomgr/iomgr_custom.h +2 -0
  138. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +93 -0
  139. data/src/core/lib/iomgr/iomgr_windows.cc +1 -0
  140. data/src/core/lib/iomgr/lockfree_event.cc +3 -3
  141. data/src/core/lib/iomgr/port.h +11 -0
  142. data/src/core/lib/iomgr/resource_quota.cc +40 -37
  143. data/src/core/lib/iomgr/socket_utils_common_posix.cc +6 -2
  144. data/src/core/lib/iomgr/socket_windows.cc +19 -0
  145. data/src/core/lib/iomgr/socket_windows.h +8 -0
  146. data/src/core/lib/iomgr/tcp_client_cfstream.cc +216 -0
  147. data/src/core/lib/iomgr/tcp_client_custom.cc +2 -2
  148. data/src/core/lib/iomgr/tcp_client_posix.cc +3 -3
  149. data/src/core/lib/iomgr/tcp_client_windows.cc +1 -1
  150. data/src/core/lib/iomgr/tcp_custom.cc +9 -9
  151. data/src/core/lib/iomgr/tcp_posix.cc +41 -41
  152. data/src/core/lib/iomgr/tcp_server_custom.cc +3 -3
  153. data/src/core/lib/iomgr/tcp_server_posix.cc +14 -1
  154. data/src/core/lib/iomgr/tcp_server_windows.cc +2 -2
  155. data/src/core/lib/iomgr/tcp_windows.cc +7 -9
  156. data/src/core/lib/iomgr/timer_generic.cc +16 -16
  157. data/src/core/lib/iomgr/timer_manager.cc +12 -11
  158. data/src/core/lib/profiling/basic_timers.cc +10 -4
  159. data/src/core/lib/security/context/security_context.cc +6 -7
  160. data/src/core/lib/security/context/security_context.h +3 -4
  161. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -1
  162. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +2 -3
  163. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  164. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +7 -7
  165. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +7 -5
  166. data/src/core/lib/security/security_connector/security_connector.cc +0 -1
  167. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +3 -2
  168. data/src/core/lib/security/security_connector/ssl_utils.cc +30 -26
  169. data/src/core/lib/security/security_connector/ssl_utils.h +5 -1
  170. data/src/core/lib/security/transport/client_auth_filter.cc +7 -11
  171. data/src/core/lib/security/transport/secure_endpoint.cc +4 -4
  172. data/src/core/lib/security/transport/server_auth_filter.cc +2 -3
  173. data/src/core/lib/slice/slice.cc +99 -116
  174. data/src/core/lib/slice/slice_buffer.cc +5 -0
  175. data/src/core/lib/slice/slice_intern.cc +38 -95
  176. data/src/core/lib/slice/slice_internal.h +200 -2
  177. data/src/core/lib/surface/api_trace.h +1 -1
  178. data/src/core/lib/surface/call.cc +41 -35
  179. data/src/core/lib/surface/call.h +7 -2
  180. data/src/core/lib/surface/call_details.cc +0 -1
  181. data/src/core/lib/surface/completion_queue.cc +36 -27
  182. data/src/core/lib/surface/init.cc +3 -4
  183. data/src/core/lib/surface/lame_client.cc +1 -1
  184. data/src/core/lib/surface/server.cc +18 -25
  185. data/src/core/lib/surface/version.cc +1 -1
  186. data/src/core/lib/transport/bdp_estimator.cc +3 -3
  187. data/src/core/lib/transport/bdp_estimator.h +2 -2
  188. data/src/core/lib/transport/connectivity_state.cc +10 -40
  189. data/src/core/lib/transport/connectivity_state.h +0 -8
  190. data/src/core/lib/transport/error_utils.cc +12 -0
  191. data/src/core/lib/transport/metadata.cc +206 -278
  192. data/src/core/lib/transport/metadata.h +205 -10
  193. data/src/core/lib/transport/static_metadata.cc +108 -116
  194. data/src/core/lib/transport/static_metadata.h +1 -2
  195. data/src/core/lib/transport/status_metadata.cc +3 -3
  196. data/src/core/lib/transport/transport.cc +29 -66
  197. data/src/core/lib/transport/transport.h +36 -8
  198. data/src/core/lib/transport/transport_impl.h +1 -1
  199. data/src/core/tsi/fake_transport_security.cc +4 -4
  200. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +1 -1
  201. data/src/core/tsi/ssl_transport_security.cc +1 -1
  202. data/src/ruby/ext/grpc/rb_grpc.c +1 -1
  203. data/src/ruby/lib/grpc/errors.rb +22 -3
  204. data/src/ruby/lib/grpc/generic/bidi_call.rb +1 -1
  205. data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
  206. data/src/ruby/lib/grpc/version.rb +1 -1
  207. data/src/ruby/spec/errors_spec.rb +141 -0
  208. metadata +57 -33
  209. data/src/core/lib/gpr/arena.cc +0 -192
@@ -33,6 +33,10 @@
33
33
  #define GROW(x) (3 * (x) / 2)
34
34
 
35
35
  static void maybe_embiggen(grpc_slice_buffer* sb) {
36
+ if (sb->count == 0) {
37
+ sb->slices = sb->base_slices;
38
+ }
39
+
36
40
  /* How far away from sb->base_slices is sb->slices pointer */
37
41
  size_t slice_offset = static_cast<size_t>(sb->slices - sb->base_slices);
38
42
  size_t slice_count = sb->count + slice_offset;
@@ -177,6 +181,7 @@ void grpc_slice_buffer_reset_and_unref_internal(grpc_slice_buffer* sb) {
177
181
 
178
182
  sb->count = 0;
179
183
  sb->length = 0;
184
+ sb->slices = sb->base_slices;
180
185
  }
181
186
 
182
187
  void grpc_slice_buffer_reset_and_unref(grpc_slice_buffer* sb) {
@@ -27,6 +27,7 @@
27
27
  #include <grpc/support/log.h>
28
28
 
29
29
  #include "src/core/lib/gpr/murmur_hash.h"
30
+ #include "src/core/lib/gprpp/sync.h"
30
31
  #include "src/core/lib/iomgr/iomgr_internal.h" /* for iomgr_abort_on_leaks() */
31
32
  #include "src/core/lib/profiling/timers.h"
32
33
  #include "src/core/lib/slice/slice_string_helpers.h"
@@ -39,24 +40,17 @@
39
40
  #define TABLE_IDX(hash, capacity) (((hash) >> LOG2_SHARD_COUNT) % (capacity))
40
41
  #define SHARD_IDX(hash) ((hash) & ((1 << LOG2_SHARD_COUNT) - 1))
41
42
 
42
- typedef struct interned_slice_refcount {
43
- grpc_slice_refcount base;
44
- grpc_slice_refcount sub;
45
- size_t length;
46
- gpr_atm refcnt;
47
- uint32_t hash;
48
- struct interned_slice_refcount* bucket_next;
49
- } interned_slice_refcount;
43
+ using grpc_core::InternedSliceRefcount;
50
44
 
51
45
  typedef struct slice_shard {
52
46
  gpr_mu mu;
53
- interned_slice_refcount** strs;
47
+ InternedSliceRefcount** strs;
54
48
  size_t count;
55
49
  size_t capacity;
56
50
  } slice_shard;
57
51
 
58
52
  /* hash seed: decided at initialization time */
59
- static uint32_t g_hash_seed;
53
+ uint32_t g_hash_seed;
60
54
  static int g_forced_hash_seed = 0;
61
55
 
62
56
  static slice_shard g_shards[SHARD_COUNT];
@@ -69,73 +63,35 @@ typedef struct {
69
63
  static static_metadata_hash_ent
70
64
  static_metadata_hash[4 * GRPC_STATIC_MDSTR_COUNT];
71
65
  static uint32_t max_static_metadata_hash_probe;
72
- static uint32_t static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
66
+ uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
73
67
 
74
- static void interned_slice_ref(void* p) {
75
- interned_slice_refcount* s = static_cast<interned_slice_refcount*>(p);
76
- GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) > 0);
77
- }
68
+ namespace grpc_core {
78
69
 
79
- static void interned_slice_destroy(interned_slice_refcount* s) {
80
- slice_shard* shard = &g_shards[SHARD_IDX(s->hash)];
81
- gpr_mu_lock(&shard->mu);
82
- GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
83
- interned_slice_refcount** prev_next;
84
- interned_slice_refcount* cur;
85
- for (prev_next = &shard->strs[TABLE_IDX(s->hash, shard->capacity)],
70
+ InternedSliceRefcount::~InternedSliceRefcount() {
71
+ slice_shard* shard = &g_shards[SHARD_IDX(this->hash)];
72
+ MutexLock lock(&shard->mu);
73
+ InternedSliceRefcount** prev_next;
74
+ InternedSliceRefcount* cur;
75
+ for (prev_next = &shard->strs[TABLE_IDX(this->hash, shard->capacity)],
86
76
  cur = *prev_next;
87
- cur != s; prev_next = &cur->bucket_next, cur = cur->bucket_next)
77
+ cur != this; prev_next = &cur->bucket_next, cur = cur->bucket_next)
88
78
  ;
89
79
  *prev_next = cur->bucket_next;
90
80
  shard->count--;
91
- gpr_free(s);
92
- gpr_mu_unlock(&shard->mu);
93
- }
94
-
95
- static void interned_slice_unref(void* p) {
96
- interned_slice_refcount* s = static_cast<interned_slice_refcount*>(p);
97
- if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
98
- interned_slice_destroy(s);
99
- }
100
- }
101
-
102
- static void interned_slice_sub_ref(void* p) {
103
- interned_slice_ref((static_cast<char*>(p)) -
104
- offsetof(interned_slice_refcount, sub));
105
- }
106
-
107
- static void interned_slice_sub_unref(void* p) {
108
- interned_slice_unref((static_cast<char*>(p)) -
109
- offsetof(interned_slice_refcount, sub));
110
- }
111
-
112
- static uint32_t interned_slice_hash(grpc_slice slice) {
113
- interned_slice_refcount* s =
114
- reinterpret_cast<interned_slice_refcount*>(slice.refcount);
115
- return s->hash;
116
- }
117
-
118
- static int interned_slice_eq(grpc_slice a, grpc_slice b) {
119
- return a.refcount == b.refcount;
120
81
  }
121
82
 
122
- static const grpc_slice_refcount_vtable interned_slice_vtable = {
123
- interned_slice_ref, interned_slice_unref, interned_slice_eq,
124
- interned_slice_hash};
125
- static const grpc_slice_refcount_vtable interned_slice_sub_vtable = {
126
- interned_slice_sub_ref, interned_slice_sub_unref,
127
- grpc_slice_default_eq_impl, grpc_slice_default_hash_impl};
83
+ } // namespace grpc_core
128
84
 
129
85
  static void grow_shard(slice_shard* shard) {
130
86
  GPR_TIMER_SCOPE("grow_strtab", 0);
131
87
 
132
88
  size_t capacity = shard->capacity * 2;
133
89
  size_t i;
134
- interned_slice_refcount** strtab;
135
- interned_slice_refcount *s, *next;
90
+ InternedSliceRefcount** strtab;
91
+ InternedSliceRefcount *s, *next;
136
92
 
137
- strtab = static_cast<interned_slice_refcount**>(
138
- gpr_zalloc(sizeof(interned_slice_refcount*) * capacity));
93
+ strtab = static_cast<InternedSliceRefcount**>(
94
+ gpr_zalloc(sizeof(InternedSliceRefcount*) * capacity));
139
95
 
140
96
  for (i = 0; i < shard->capacity; i++) {
141
97
  for (s = shard->strs[i]; s; s = next) {
@@ -150,7 +106,7 @@ static void grow_shard(slice_shard* shard) {
150
106
  shard->capacity = capacity;
151
107
  }
152
108
 
153
- static grpc_slice materialize(interned_slice_refcount* s) {
109
+ static grpc_slice materialize(InternedSliceRefcount* s) {
154
110
  grpc_slice slice;
155
111
  slice.refcount = &s->base;
156
112
  slice.data.refcounted.bytes = reinterpret_cast<uint8_t*>(s + 1);
@@ -164,7 +120,7 @@ uint32_t grpc_slice_default_hash_impl(grpc_slice s) {
164
120
  }
165
121
 
166
122
  uint32_t grpc_static_slice_hash(grpc_slice s) {
167
- return static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(s)];
123
+ return grpc_static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(s)];
168
124
  }
169
125
 
170
126
  int grpc_static_slice_eq(grpc_slice a, grpc_slice b) {
@@ -173,7 +129,7 @@ int grpc_static_slice_eq(grpc_slice a, grpc_slice b) {
173
129
 
174
130
  uint32_t grpc_slice_hash(grpc_slice s) {
175
131
  return s.refcount == nullptr ? grpc_slice_default_hash_impl(s)
176
- : s.refcount->vtable->hash(s);
132
+ : s.refcount->Hash(s);
177
133
  }
178
134
 
179
135
  grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice,
@@ -197,8 +153,9 @@ grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice,
197
153
  }
198
154
 
199
155
  bool grpc_slice_is_interned(const grpc_slice& slice) {
200
- return (slice.refcount && slice.refcount->vtable == &interned_slice_vtable) ||
201
- GRPC_IS_STATIC_METADATA_STRING(slice);
156
+ return (slice.refcount &&
157
+ (slice.refcount->GetType() == grpc_slice_refcount::Type::INTERNED ||
158
+ GRPC_IS_STATIC_METADATA_STRING(slice)));
202
159
  }
203
160
 
204
161
  grpc_slice grpc_slice_intern(grpc_slice slice) {
@@ -208,6 +165,7 @@ grpc_slice grpc_slice_intern(grpc_slice slice) {
208
165
  }
209
166
 
210
167
  uint32_t hash = grpc_slice_hash(slice);
168
+
211
169
  for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) {
212
170
  static_metadata_hash_ent ent =
213
171
  static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)];
@@ -217,7 +175,7 @@ grpc_slice grpc_slice_intern(grpc_slice slice) {
217
175
  }
218
176
  }
219
177
 
220
- interned_slice_refcount* s;
178
+ InternedSliceRefcount* s;
221
179
  slice_shard* shard = &g_shards[SHARD_IDX(hash)];
222
180
 
223
181
  gpr_mu_lock(&shard->mu);
@@ -226,14 +184,7 @@ grpc_slice grpc_slice_intern(grpc_slice slice) {
226
184
  size_t idx = TABLE_IDX(hash, shard->capacity);
227
185
  for (s = shard->strs[idx]; s; s = s->bucket_next) {
228
186
  if (s->hash == hash && grpc_slice_eq(slice, materialize(s))) {
229
- if (gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) == 0) {
230
- /* If we get here, we've added a ref to something that was about to
231
- * die - drop it immediately.
232
- * The *only* possible path here (given the shard mutex) should be to
233
- * drop from one ref back to zero - assert that with a CAS */
234
- GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0));
235
- /* and treat this as if we were never here... sshhh */
236
- } else {
187
+ if (s->refcnt.RefIfNonZero()) {
237
188
  gpr_mu_unlock(&shard->mu);
238
189
  return materialize(s);
239
190
  }
@@ -242,27 +193,20 @@ grpc_slice grpc_slice_intern(grpc_slice slice) {
242
193
 
243
194
  /* not found: create a new string */
244
195
  /* string data goes after the internal_string header */
245
- s = static_cast<interned_slice_refcount*>(
196
+ s = static_cast<InternedSliceRefcount*>(
246
197
  gpr_malloc(sizeof(*s) + GRPC_SLICE_LENGTH(slice)));
247
- gpr_atm_rel_store(&s->refcnt, 1);
248
- s->length = GRPC_SLICE_LENGTH(slice);
249
- s->hash = hash;
250
- s->base.vtable = &interned_slice_vtable;
251
- s->base.sub_refcount = &s->sub;
252
- s->sub.vtable = &interned_slice_sub_vtable;
253
- s->sub.sub_refcount = &s->sub;
254
- s->bucket_next = shard->strs[idx];
255
- shard->strs[idx] = s;
256
- memcpy(s + 1, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice));
257
198
 
199
+ new (s) grpc_core::InternedSliceRefcount(GRPC_SLICE_LENGTH(slice), hash,
200
+ shard->strs[idx]);
201
+ memcpy(reinterpret_cast<char*>(s + 1), GRPC_SLICE_START_PTR(slice),
202
+ GRPC_SLICE_LENGTH(slice));
203
+ shard->strs[idx] = s;
258
204
  shard->count++;
259
-
260
205
  if (shard->count > shard->capacity * 2) {
261
206
  grow_shard(shard);
262
207
  }
263
208
 
264
209
  gpr_mu_unlock(&shard->mu);
265
-
266
210
  return materialize(s);
267
211
  }
268
212
 
@@ -280,7 +224,7 @@ void grpc_slice_intern_init(void) {
280
224
  gpr_mu_init(&shard->mu);
281
225
  shard->count = 0;
282
226
  shard->capacity = INITIAL_SHARD_CAPACITY;
283
- shard->strs = static_cast<interned_slice_refcount**>(
227
+ shard->strs = static_cast<InternedSliceRefcount**>(
284
228
  gpr_zalloc(sizeof(*shard->strs) * shard->capacity));
285
229
  }
286
230
  for (size_t i = 0; i < GPR_ARRAY_SIZE(static_metadata_hash); i++) {
@@ -289,13 +233,13 @@ void grpc_slice_intern_init(void) {
289
233
  }
290
234
  max_static_metadata_hash_probe = 0;
291
235
  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
292
- static_metadata_hash_values[i] =
236
+ grpc_static_metadata_hash_values[i] =
293
237
  grpc_slice_default_hash_impl(grpc_static_slice_table[i]);
294
238
  for (size_t j = 0; j < GPR_ARRAY_SIZE(static_metadata_hash); j++) {
295
- size_t slot = (static_metadata_hash_values[i] + j) %
239
+ size_t slot = (grpc_static_metadata_hash_values[i] + j) %
296
240
  GPR_ARRAY_SIZE(static_metadata_hash);
297
241
  if (static_metadata_hash[slot].idx == GRPC_STATIC_MDSTR_COUNT) {
298
- static_metadata_hash[slot].hash = static_metadata_hash_values[i];
242
+ static_metadata_hash[slot].hash = grpc_static_metadata_hash_values[i];
299
243
  static_metadata_hash[slot].idx = static_cast<uint32_t>(i);
300
244
  if (j > max_static_metadata_hash_probe) {
301
245
  max_static_metadata_hash_probe = static_cast<uint32_t>(j);
@@ -315,8 +259,7 @@ void grpc_slice_intern_shutdown(void) {
315
259
  gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked",
316
260
  shard->count);
317
261
  for (size_t j = 0; j < shard->capacity; j++) {
318
- for (interned_slice_refcount* s = shard->strs[j]; s;
319
- s = s->bucket_next) {
262
+ for (InternedSliceRefcount* s = shard->strs[j]; s; s = s->bucket_next) {
320
263
  char* text =
321
264
  grpc_dump_slice(materialize(s), GPR_DUMP_HEX | GPR_DUMP_ASCII);
322
265
  gpr_log(GPR_DEBUG, "LEAKED: %s", text);
@@ -23,17 +23,215 @@
23
23
 
24
24
  #include <grpc/slice.h>
25
25
  #include <grpc/slice_buffer.h>
26
+ #include <string.h>
27
+
28
+ #include "src/core/lib/gpr/murmur_hash.h"
29
+ #include "src/core/lib/gprpp/ref_counted.h"
30
+ #include "src/core/lib/transport/static_metadata.h"
31
+
32
+ // Interned slices have specific fast-path operations for hashing. To inline
33
+ // these operations, we need to forward declare them here.
34
+ extern uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
35
+ extern uint32_t g_hash_seed;
36
+
37
+ // grpc_slice_refcount : A reference count for grpc_slice.
38
+ //
39
+ // Non-inlined grpc_slice objects are refcounted. Historically this was
40
+ // implemented via grpc_slice_refcount, a C-style polymorphic class using a
41
+ // manually managed vtable of operations. Subclasses would define their own
42
+ // vtable; the 'virtual' methods (ref, unref, equals and hash) would simply call
43
+ // the function pointers in the vtable as necessary.
44
+ //
45
+ // Unfortunately, this leads to some inefficiencies in the generated code that
46
+ // can be improved upon. For example, equality checking for interned slices is a
47
+ // simple equality check on the refcount pointer. With the vtable approach, this
48
+ // would translate to roughly the following (high-level) instructions:
49
+ //
50
+ // grpc_slice_equals(slice1, slice2):
51
+ // load vtable->eq -> eq_func
52
+ // call eq_func(slice1, slice2)
53
+ //
54
+ // interned_slice_equals(slice1, slice2)
55
+ // load slice1.ref -> r1
56
+ // load slice2.ref -> r2
57
+ // cmp r1, r2 -> retval
58
+ // ret retval
59
+ //
60
+ // This leads to a function call for a function defined in another translation
61
+ // unit, which imposes memory barriers, which reduces the compiler's ability to
62
+ // optimize (in addition to the added overhead of call/ret). Additionally, it
63
+ // may be harder to reason about branch prediction when we're jumping to
64
+ // essentially arbitrarily provided function pointers.
65
+ //
66
+ // In addition, it is arguable that while virtualization was helpful for
67
+ // Equals()/Hash() methods, that it was fundamentally unnecessary for
68
+ // Ref()/Unref().
69
+ //
70
+ // Instead, grpc_slice_refcount provides the same functionality as the C-style
71
+ // virtual class, but in a de-virtualized manner - Eq(), Hash(), Ref() and
72
+ // Unref() are provided within this header file. Fastpaths for Eq()/Hash()
73
+ // (interned and static metadata slices), as well as the Ref() operation, can
74
+ // all be inlined without any memory barriers.
75
+ //
76
+ // It does this by:
77
+ // 1. Using grpc_core::RefCount<> (header-only) for Ref/Unref. Two special cases
78
+ // need support: No-op ref/unref (eg. static metadata slices) and stream
79
+ // slice references (where all the slices share the streamref). This is in
80
+ // addition to the normal case of '1 slice, 1 ref'.
81
+ // To support these cases, we explicitly track a nullable pointer to the
82
+ // underlying RefCount<>. No-op ref/unref is used by checking the pointer for
83
+ // null, and doing nothing if it is. Both stream slice refs and 'normal'
84
+ // slices use the same path for Ref/Unref (by targeting the non-null
85
+ // pointer).
86
+ //
87
+ // 2. introducing the notion of grpc_slice_refcount::Type. This describes if a
88
+ // slice ref is used by a static metadata slice, an interned slice, or other
89
+ // slices. We switch on the slice ref type in order to provide fastpaths for
90
+ // Equals() and Hash().
91
+ //
92
+ // In total, this saves us roughly 1-2% latency for unary calls, with smaller
93
+ // calls benefitting. The effect is present, but not as useful, for larger calls
94
+ // where the cost of sending the data dominates.
95
+ struct grpc_slice_refcount {
96
+ public:
97
+ enum class Type {
98
+ STATIC, // Refcount for a static metadata slice.
99
+ INTERNED, // Refcount for an interned slice.
100
+ REGULAR // Refcount for non-static-metadata, non-interned slices.
101
+ };
102
+ typedef void (*DestroyerFn)(void*);
103
+
104
+ grpc_slice_refcount() = default;
105
+
106
+ explicit grpc_slice_refcount(grpc_slice_refcount* sub) : sub_refcount_(sub) {}
107
+ // Regular constructor for grpc_slice_refcount.
108
+ //
109
+ // Parameters:
110
+ // 1. grpc_slice_refcount::Type type
111
+ // Whether we are the refcount for a static
112
+ // metadata slice, an interned slice, or any other kind of slice.
113
+ //
114
+ // 2. RefCount* ref
115
+ // The pointer to the actual underlying grpc_core::RefCount. Rather than
116
+ // performing struct offset computations as in the original implementation to
117
+ // get to the refcount, which requires a virtual method, we devirtualize by
118
+ // using a nullable pointer to allow a single pair of Ref/Unref methods.
119
+ //
120
+ // 3. DestroyerFn destroyer_fn
121
+ // Called when the refcount goes to 0, with destroyer_arg as parameter.
122
+ //
123
+ // 4. void* destroyer_arg
124
+ // Argument for the virtualized destructor.
125
+ //
126
+ // 5. grpc_slice_refcount* sub
127
+ // Argument used for interned slices.
128
+ grpc_slice_refcount(grpc_slice_refcount::Type type, grpc_core::RefCount* ref,
129
+ DestroyerFn destroyer_fn, void* destroyer_arg,
130
+ grpc_slice_refcount* sub)
131
+ : ref_(ref),
132
+ ref_type_(type),
133
+ sub_refcount_(sub),
134
+ dest_fn_(destroyer_fn),
135
+ destroy_fn_arg_(destroyer_arg) {}
136
+ // Initializer for static refcounts.
137
+ grpc_slice_refcount(grpc_slice_refcount* sub, Type type)
138
+ : ref_type_(type), sub_refcount_(sub) {}
139
+
140
+ Type GetType() const { return ref_type_; }
141
+
142
+ int Eq(const grpc_slice& a, const grpc_slice& b);
143
+
144
+ uint32_t Hash(const grpc_slice& slice);
145
+ void Ref() {
146
+ if (ref_ == nullptr) return;
147
+ ref_->RefNonZero();
148
+ }
149
+ void Unref() {
150
+ if (ref_ == nullptr) return;
151
+ if (ref_->Unref()) {
152
+ dest_fn_(destroy_fn_arg_);
153
+ }
154
+ }
155
+
156
+ grpc_slice_refcount* sub_refcount() const { return sub_refcount_; }
157
+
158
+ private:
159
+ grpc_core::RefCount* ref_ = nullptr;
160
+ const Type ref_type_ = Type::REGULAR;
161
+ grpc_slice_refcount* sub_refcount_ = this;
162
+ DestroyerFn dest_fn_ = nullptr;
163
+ void* destroy_fn_arg_ = nullptr;
164
+ };
165
+
166
+ namespace grpc_core {
167
+
168
+ struct InternedSliceRefcount {
169
+ static void Destroy(void* arg) {
170
+ auto* rc = static_cast<InternedSliceRefcount*>(arg);
171
+ rc->~InternedSliceRefcount();
172
+ gpr_free(rc);
173
+ }
174
+
175
+ InternedSliceRefcount(size_t length, uint32_t hash,
176
+ InternedSliceRefcount* bucket_next)
177
+ : base(grpc_slice_refcount::Type::INTERNED, &refcnt, Destroy, this, &sub),
178
+ sub(grpc_slice_refcount::Type::REGULAR, &refcnt, Destroy, this, &sub),
179
+ length(length),
180
+ hash(hash),
181
+ bucket_next(bucket_next) {}
182
+
183
+ ~InternedSliceRefcount();
184
+
185
+ grpc_slice_refcount base;
186
+ grpc_slice_refcount sub;
187
+ const size_t length;
188
+ RefCount refcnt;
189
+ const uint32_t hash;
190
+ InternedSliceRefcount* bucket_next;
191
+ };
192
+
193
+ } // namespace grpc_core
194
+
195
+ inline int grpc_slice_refcount::Eq(const grpc_slice& a, const grpc_slice& b) {
196
+ switch (ref_type_) {
197
+ case Type::STATIC:
198
+ return GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b);
199
+ case Type::INTERNED:
200
+ return a.refcount == b.refcount;
201
+ case Type::REGULAR:
202
+ break;
203
+ }
204
+ if (GRPC_SLICE_LENGTH(a) != GRPC_SLICE_LENGTH(b)) return false;
205
+ if (GRPC_SLICE_LENGTH(a) == 0) return true;
206
+ return 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
207
+ GRPC_SLICE_LENGTH(a));
208
+ }
209
+
210
+ inline uint32_t grpc_slice_refcount::Hash(const grpc_slice& slice) {
211
+ switch (ref_type_) {
212
+ case Type::STATIC:
213
+ return ::grpc_static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(
214
+ slice)];
215
+ case Type::INTERNED:
216
+ return reinterpret_cast<grpc_core::InternedSliceRefcount*>(slice.refcount)
217
+ ->hash;
218
+ case Type::REGULAR:
219
+ break;
220
+ }
221
+ return gpr_murmur_hash3(GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice),
222
+ g_hash_seed);
223
+ }
26
224
 
27
225
  inline const grpc_slice& grpc_slice_ref_internal(const grpc_slice& slice) {
28
226
  if (slice.refcount) {
29
- slice.refcount->vtable->ref(slice.refcount);
227
+ slice.refcount->Ref();
30
228
  }
31
229
  return slice;
32
230
  }
33
231
 
34
232
  inline void grpc_slice_unref_internal(const grpc_slice& slice) {
35
233
  if (slice.refcount) {
36
- slice.refcount->vtable->unref(slice.refcount);
234
+ slice.refcount->Unref();
37
235
  }
38
236
  }
39
237