Progress towards mdstr elimination
diff --git a/BUILD b/BUILD
index 9088b61..22680a6 100644
--- a/BUILD
+++ b/BUILD
@@ -231,6 +231,7 @@
     "src/core/lib/json/json_reader.h",
     "src/core/lib/json/json_writer.h",
     "src/core/lib/slice/percent_encoding.h",
+    "src/core/lib/slice/slice_hash_table.h",
     "src/core/lib/slice/slice_string_helpers.h",
     "src/core/lib/surface/api_trace.h",
     "src/core/lib/surface/call.h",
@@ -245,7 +246,6 @@
     "src/core/lib/surface/server.h",
     "src/core/lib/transport/byte_stream.h",
     "src/core/lib/transport/connectivity_state.h",
-    "src/core/lib/transport/mdstr_hash_table.h",
     "src/core/lib/transport/metadata.h",
     "src/core/lib/transport/metadata_batch.h",
     "src/core/lib/transport/method_config.h",
@@ -413,6 +413,7 @@
     "src/core/lib/slice/percent_encoding.c",
     "src/core/lib/slice/slice.c",
     "src/core/lib/slice/slice_buffer.c",
+    "src/core/lib/slice/slice_hash_table.c",
     "src/core/lib/slice/slice_intern.c",
     "src/core/lib/slice/slice_string_helpers.c",
     "src/core/lib/surface/alarm.c",
@@ -435,7 +436,6 @@
     "src/core/lib/surface/version.c",
     "src/core/lib/transport/byte_stream.c",
     "src/core/lib/transport/connectivity_state.c",
-    "src/core/lib/transport/mdstr_hash_table.c",
     "src/core/lib/transport/metadata.c",
     "src/core/lib/transport/metadata_batch.c",
     "src/core/lib/transport/method_config.c",
@@ -667,6 +667,7 @@
     "src/core/lib/json/json_reader.h",
     "src/core/lib/json/json_writer.h",
     "src/core/lib/slice/percent_encoding.h",
+    "src/core/lib/slice/slice_hash_table.h",
     "src/core/lib/slice/slice_string_helpers.h",
     "src/core/lib/surface/api_trace.h",
     "src/core/lib/surface/call.h",
@@ -681,7 +682,6 @@
     "src/core/lib/surface/server.h",
     "src/core/lib/transport/byte_stream.h",
     "src/core/lib/transport/connectivity_state.h",
-    "src/core/lib/transport/mdstr_hash_table.h",
     "src/core/lib/transport/metadata.h",
     "src/core/lib/transport/metadata_batch.h",
     "src/core/lib/transport/method_config.h",
@@ -834,6 +834,7 @@
     "src/core/lib/slice/percent_encoding.c",
     "src/core/lib/slice/slice.c",
     "src/core/lib/slice/slice_buffer.c",
+    "src/core/lib/slice/slice_hash_table.c",
     "src/core/lib/slice/slice_intern.c",
     "src/core/lib/slice/slice_string_helpers.c",
     "src/core/lib/surface/alarm.c",
@@ -856,7 +857,6 @@
     "src/core/lib/surface/version.c",
     "src/core/lib/transport/byte_stream.c",
     "src/core/lib/transport/connectivity_state.c",
-    "src/core/lib/transport/mdstr_hash_table.c",
     "src/core/lib/transport/metadata.c",
     "src/core/lib/transport/metadata_batch.c",
     "src/core/lib/transport/method_config.c",
@@ -1058,6 +1058,7 @@
     "src/core/lib/json/json_reader.h",
     "src/core/lib/json/json_writer.h",
     "src/core/lib/slice/percent_encoding.h",
+    "src/core/lib/slice/slice_hash_table.h",
     "src/core/lib/slice/slice_string_helpers.h",
     "src/core/lib/surface/api_trace.h",
     "src/core/lib/surface/call.h",
@@ -1072,7 +1073,6 @@
     "src/core/lib/surface/server.h",
     "src/core/lib/transport/byte_stream.h",
     "src/core/lib/transport/connectivity_state.h",
-    "src/core/lib/transport/mdstr_hash_table.h",
     "src/core/lib/transport/metadata.h",
     "src/core/lib/transport/metadata_batch.h",
     "src/core/lib/transport/method_config.h",
@@ -1217,6 +1217,7 @@
     "src/core/lib/slice/percent_encoding.c",
     "src/core/lib/slice/slice.c",
     "src/core/lib/slice/slice_buffer.c",
+    "src/core/lib/slice/slice_hash_table.c",
     "src/core/lib/slice/slice_intern.c",
     "src/core/lib/slice/slice_string_helpers.c",
     "src/core/lib/surface/alarm.c",
@@ -1239,7 +1240,6 @@
     "src/core/lib/surface/version.c",
     "src/core/lib/transport/byte_stream.c",
     "src/core/lib/transport/connectivity_state.c",
-    "src/core/lib/transport/mdstr_hash_table.c",
     "src/core/lib/transport/metadata.c",
     "src/core/lib/transport/metadata_batch.c",
     "src/core/lib/transport/method_config.c",
@@ -2084,6 +2084,7 @@
     "src/core/lib/slice/percent_encoding.c",
     "src/core/lib/slice/slice.c",
     "src/core/lib/slice/slice_buffer.c",
+    "src/core/lib/slice/slice_hash_table.c",
     "src/core/lib/slice/slice_intern.c",
     "src/core/lib/slice/slice_string_helpers.c",
     "src/core/lib/surface/alarm.c",
@@ -2106,7 +2107,6 @@
     "src/core/lib/surface/version.c",
     "src/core/lib/transport/byte_stream.c",
     "src/core/lib/transport/connectivity_state.c",
-    "src/core/lib/transport/mdstr_hash_table.c",
     "src/core/lib/transport/metadata.c",
     "src/core/lib/transport/metadata_batch.c",
     "src/core/lib/transport/method_config.c",
@@ -2317,6 +2317,7 @@
     "src/core/lib/json/json_reader.h",
     "src/core/lib/json/json_writer.h",
     "src/core/lib/slice/percent_encoding.h",
+    "src/core/lib/slice/slice_hash_table.h",
     "src/core/lib/slice/slice_string_helpers.h",
     "src/core/lib/surface/api_trace.h",
     "src/core/lib/surface/call.h",
@@ -2331,7 +2332,6 @@
     "src/core/lib/surface/server.h",
     "src/core/lib/transport/byte_stream.h",
     "src/core/lib/transport/connectivity_state.h",
-    "src/core/lib/transport/mdstr_hash_table.h",
     "src/core/lib/transport/metadata.h",
     "src/core/lib/transport/metadata_batch.h",
     "src/core/lib/transport/method_config.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e6e7ff7..1b17f4c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -368,6 +368,7 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
   src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
@@ -390,7 +391,6 @@
   src/core/lib/surface/version.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/method_config.c
@@ -649,6 +649,7 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
   src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
@@ -671,7 +672,6 @@
   src/core/lib/surface/version.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/method_config.c
@@ -902,6 +902,7 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
   src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
@@ -924,7 +925,6 @@
   src/core/lib/surface/version.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/method_config.c
diff --git a/Makefile b/Makefile
index 4e05317..eea4e71 100644
--- a/Makefile
+++ b/Makefile
@@ -2699,6 +2699,7 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
     src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
@@ -2721,7 +2722,6 @@
     src/core/lib/surface/version.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/method_config.c \
@@ -2998,6 +2998,7 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
     src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
@@ -3020,7 +3021,6 @@
     src/core/lib/surface/version.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/method_config.c \
@@ -3288,6 +3288,7 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
     src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
@@ -3310,7 +3311,6 @@
     src/core/lib/surface/version.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/method_config.c \
@@ -3507,6 +3507,7 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
     src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
@@ -3529,7 +3530,6 @@
     src/core/lib/surface/version.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/method_config.c \
diff --git a/binding.gyp b/binding.gyp
index 0cc7762..c600ba0 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -647,6 +647,7 @@
         'src/core/lib/slice/percent_encoding.c',
         'src/core/lib/slice/slice.c',
         'src/core/lib/slice/slice_buffer.c',
+        'src/core/lib/slice/slice_hash_table.c',
         'src/core/lib/slice/slice_intern.c',
         'src/core/lib/slice/slice_string_helpers.c',
         'src/core/lib/surface/alarm.c',
@@ -669,7 +670,6 @@
         'src/core/lib/surface/version.c',
         'src/core/lib/transport/byte_stream.c',
         'src/core/lib/transport/connectivity_state.c',
-        'src/core/lib/transport/mdstr_hash_table.c',
         'src/core/lib/transport/metadata.c',
         'src/core/lib/transport/metadata_batch.c',
         'src/core/lib/transport/method_config.c',
diff --git a/build.yaml b/build.yaml
index 16a4afc..de19a3e 100644
--- a/build.yaml
+++ b/build.yaml
@@ -238,6 +238,7 @@
   - src/core/lib/json/json_reader.h
   - src/core/lib/json/json_writer.h
   - src/core/lib/slice/percent_encoding.h
+  - src/core/lib/slice/slice_hash_table.h
   - src/core/lib/slice/slice_string_helpers.h
   - src/core/lib/surface/api_trace.h
   - src/core/lib/surface/call.h
@@ -252,7 +253,6 @@
   - src/core/lib/surface/server.h
   - src/core/lib/transport/byte_stream.h
   - src/core/lib/transport/connectivity_state.h
-  - src/core/lib/transport/mdstr_hash_table.h
   - src/core/lib/transport/metadata.h
   - src/core/lib/transport/metadata_batch.h
   - src/core/lib/transport/method_config.h
@@ -344,6 +344,7 @@
   - src/core/lib/slice/percent_encoding.c
   - src/core/lib/slice/slice.c
   - src/core/lib/slice/slice_buffer.c
+  - src/core/lib/slice/slice_hash_table.c
   - src/core/lib/slice/slice_intern.c
   - src/core/lib/slice/slice_string_helpers.c
   - src/core/lib/surface/alarm.c
@@ -366,7 +367,6 @@
   - src/core/lib/surface/version.c
   - src/core/lib/transport/byte_stream.c
   - src/core/lib/transport/connectivity_state.c
-  - src/core/lib/transport/mdstr_hash_table.c
   - src/core/lib/transport/metadata.c
   - src/core/lib/transport/metadata_batch.c
   - src/core/lib/transport/method_config.c
diff --git a/config.m4 b/config.m4
index 3c9b098..d87adfd 100644
--- a/config.m4
+++ b/config.m4
@@ -163,6 +163,7 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
     src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
@@ -185,7 +186,6 @@
     src/core/lib/surface/version.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/method_config.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index e73b8e0..5902701 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -321,6 +321,7 @@
                       'src/core/lib/json/json_reader.h',
                       'src/core/lib/json/json_writer.h',
                       'src/core/lib/slice/percent_encoding.h',
+                      'src/core/lib/slice/slice_hash_table.h',
                       'src/core/lib/slice/slice_string_helpers.h',
                       'src/core/lib/surface/api_trace.h',
                       'src/core/lib/surface/call.h',
@@ -335,7 +336,6 @@
                       'src/core/lib/surface/server.h',
                       'src/core/lib/transport/byte_stream.h',
                       'src/core/lib/transport/connectivity_state.h',
-                      'src/core/lib/transport/mdstr_hash_table.h',
                       'src/core/lib/transport/metadata.h',
                       'src/core/lib/transport/metadata_batch.h',
                       'src/core/lib/transport/method_config.h',
@@ -507,6 +507,7 @@
                       'src/core/lib/slice/percent_encoding.c',
                       'src/core/lib/slice/slice.c',
                       'src/core/lib/slice/slice_buffer.c',
+                      'src/core/lib/slice/slice_hash_table.c',
                       'src/core/lib/slice/slice_intern.c',
                       'src/core/lib/slice/slice_string_helpers.c',
                       'src/core/lib/surface/alarm.c',
@@ -529,7 +530,6 @@
                       'src/core/lib/surface/version.c',
                       'src/core/lib/transport/byte_stream.c',
                       'src/core/lib/transport/connectivity_state.c',
-                      'src/core/lib/transport/mdstr_hash_table.c',
                       'src/core/lib/transport/metadata.c',
                       'src/core/lib/transport/metadata_batch.c',
                       'src/core/lib/transport/method_config.c',
@@ -725,6 +725,7 @@
                               'src/core/lib/json/json_reader.h',
                               'src/core/lib/json/json_writer.h',
                               'src/core/lib/slice/percent_encoding.h',
+                              'src/core/lib/slice/slice_hash_table.h',
                               'src/core/lib/slice/slice_string_helpers.h',
                               'src/core/lib/surface/api_trace.h',
                               'src/core/lib/surface/call.h',
@@ -739,7 +740,6 @@
                               'src/core/lib/surface/server.h',
                               'src/core/lib/transport/byte_stream.h',
                               'src/core/lib/transport/connectivity_state.h',
-                              'src/core/lib/transport/mdstr_hash_table.h',
                               'src/core/lib/transport/metadata.h',
                               'src/core/lib/transport/metadata_batch.h',
                               'src/core/lib/transport/method_config.h',
diff --git a/grpc.def b/grpc.def
index 61bc173..02a18f8 100644
--- a/grpc.def
+++ b/grpc.def
@@ -149,9 +149,12 @@
     grpc_slice_sub_no_ref
     grpc_slice_split_tail
     grpc_slice_split_head
-    gpr_empty_slice
+    grpc_empty_slice
     grpc_slice_cmp
     grpc_slice_str_cmp
+    grpc_slice_buf_cmp
+    grpc_slice_buf_start_eq
+    grpc_slice_hash
     grpc_slice_buffer_init
     grpc_slice_buffer_destroy
     grpc_slice_buffer_add
diff --git a/grpc.gemspec b/grpc.gemspec
index c50fc5a..20b3757 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -241,6 +241,7 @@
   s.files += %w( src/core/lib/json/json_reader.h )
   s.files += %w( src/core/lib/json/json_writer.h )
   s.files += %w( src/core/lib/slice/percent_encoding.h )
+  s.files += %w( src/core/lib/slice/slice_hash_table.h )
   s.files += %w( src/core/lib/slice/slice_string_helpers.h )
   s.files += %w( src/core/lib/surface/api_trace.h )
   s.files += %w( src/core/lib/surface/call.h )
@@ -255,7 +256,6 @@
   s.files += %w( src/core/lib/surface/server.h )
   s.files += %w( src/core/lib/transport/byte_stream.h )
   s.files += %w( src/core/lib/transport/connectivity_state.h )
-  s.files += %w( src/core/lib/transport/mdstr_hash_table.h )
   s.files += %w( src/core/lib/transport/metadata.h )
   s.files += %w( src/core/lib/transport/metadata_batch.h )
   s.files += %w( src/core/lib/transport/method_config.h )
@@ -427,6 +427,7 @@
   s.files += %w( src/core/lib/slice/percent_encoding.c )
   s.files += %w( src/core/lib/slice/slice.c )
   s.files += %w( src/core/lib/slice/slice_buffer.c )
+  s.files += %w( src/core/lib/slice/slice_hash_table.c )
   s.files += %w( src/core/lib/slice/slice_intern.c )
   s.files += %w( src/core/lib/slice/slice_string_helpers.c )
   s.files += %w( src/core/lib/surface/alarm.c )
@@ -449,7 +450,6 @@
   s.files += %w( src/core/lib/surface/version.c )
   s.files += %w( src/core/lib/transport/byte_stream.c )
   s.files += %w( src/core/lib/transport/connectivity_state.c )
-  s.files += %w( src/core/lib/transport/mdstr_hash_table.c )
   s.files += %w( src/core/lib/transport/metadata.c )
   s.files += %w( src/core/lib/transport/metadata_batch.c )
   s.files += %w( src/core/lib/transport/method_config.c )
diff --git a/include/grpc/compression.h b/include/grpc/compression.h
index 5f285cd..659d6fe 100644
--- a/include/grpc/compression.h
+++ b/include/grpc/compression.h
@@ -34,11 +34,12 @@
 #ifndef GRPC_COMPRESSION_H
 #define GRPC_COMPRESSION_H
 
-#include <stdlib.h>
-
 #include <grpc/impl/codegen/port_platform.h>
 
+#include <stdlib.h>
+
 #include <grpc/impl/codegen/compression_types.h>
+#include <grpc/slice.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -48,8 +49,7 @@
  * grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon
  * success, 0 otherwise. */
 GRPCAPI int grpc_compression_algorithm_parse(
-    const char *name, size_t name_length,
-    grpc_compression_algorithm *algorithm);
+    grpc_slice value, grpc_compression_algorithm *algorithm);
 
 /** Updates \a name with the encoding name corresponding to a valid \a
  * algorithm. Note that \a name is statically allocated and must *not* be freed.
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 53a650f..dd9cbd5 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -119,13 +119,16 @@
    Requires s intialized, split <= s.length */
 GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
 
-GPRAPI grpc_slice gpr_empty_slice(void);
+GPRAPI grpc_slice grpc_empty_slice(void);
 
 /* Returns <0 if a < b, ==0 if a == b, >0 if a > b
    The order is arbitrary, and is not guaranteed to be stable across different
    versions of the API. */
 GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
 GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
+GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen);
+
+GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen);
 
 GPRAPI uint32_t grpc_slice_hash(grpc_slice s);
 
diff --git a/package.xml b/package.xml
index 786e25a..997cf18 100644
--- a/package.xml
+++ b/package.xml
@@ -248,6 +248,7 @@
     <file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/call.h" role="src" />
@@ -262,7 +263,6 @@
     <file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/method_config.h" role="src" />
@@ -434,6 +434,7 @@
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_intern.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/alarm.c" role="src" />
@@ -456,7 +457,6 @@
     <file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/method_config.c" role="src" />
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 7954fcf..94ca656 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -96,7 +96,7 @@
   gpr_free(p);
 }
 
-static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
+static const grpc_slice_hash_table_vtable method_parameters_vtable = {
     method_parameters_del, method_parameters_copy, method_parameters_cmp};
 
 static void *method_config_convert_value(
@@ -131,7 +131,7 @@
   char *lb_policy_name;
   grpc_lb_policy *lb_policy;
   /** maps method names to method_parameters structs */
-  grpc_mdstr_hash_table *method_params_table;
+  grpc_slice_hash_table *method_params_table;
   /** incoming resolver result - set by resolver.next() */
   grpc_channel_args *resolver_result;
   /** a list of closures that are all waiting for config to come in */
@@ -232,7 +232,7 @@
   char *lb_policy_name = NULL;
   grpc_lb_policy *lb_policy = NULL;
   grpc_lb_policy *old_lb_policy;
-  grpc_mdstr_hash_table *method_params_table = NULL;
+  grpc_slice_hash_table *method_params_table = NULL;
   grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
   bool exit_idle = false;
   grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
@@ -316,7 +316,7 @@
   old_lb_policy = chand->lb_policy;
   chand->lb_policy = lb_policy;
   if (chand->method_params_table != NULL) {
-    grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
+    grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
   }
   chand->method_params_table = method_params_table;
   if (lb_policy != NULL) {
@@ -494,7 +494,7 @@
   }
   gpr_free(chand->lb_policy_name);
   if (chand->method_params_table != NULL) {
-    grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
+    grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
   }
   grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
   grpc_pollset_set_destroy(chand->interested_parties);
@@ -529,7 +529,7 @@
   // to avoid this without breaking the grpc_deadline_state abstraction.
   grpc_deadline_state deadline_state;
 
-  grpc_mdstr *path;  // Request path.
+  grpc_slice path;  // Request path.
   gpr_timespec call_start_time;
   gpr_timespec deadline;
   wait_for_ready_value wait_for_ready_from_service_config;
@@ -926,10 +926,10 @@
   if (error == GRPC_ERROR_NONE) {
     // Get the method config table from channel data.
     gpr_mu_lock(&chand->mu);
-    grpc_mdstr_hash_table *method_params_table = NULL;
+    grpc_slice_hash_table *method_params_table = NULL;
     if (chand->method_params_table != NULL) {
       method_params_table =
-          grpc_mdstr_hash_table_ref(chand->method_params_table);
+          grpc_slice_hash_table_ref(chand->method_params_table);
     }
     gpr_mu_unlock(&chand->mu);
     // If the method config table was present, use it.
@@ -958,7 +958,7 @@
           gpr_mu_unlock(&calld->mu);
         }
       }
-      grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
+      grpc_slice_hash_table_unref(exec_ctx, method_params_table);
     }
   }
   GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
@@ -996,8 +996,8 @@
   if (chand->lb_policy != NULL) {
     // We already have a resolver result, so check for service config.
     if (chand->method_params_table != NULL) {
-      grpc_mdstr_hash_table *method_params_table =
-          grpc_mdstr_hash_table_ref(chand->method_params_table);
+      grpc_slice_hash_table *method_params_table =
+          grpc_slice_hash_table_ref(chand->method_params_table);
       gpr_mu_unlock(&chand->mu);
       method_parameters *method_params = grpc_method_config_table_get(
           exec_ctx, method_params_table, args->path);
@@ -1013,7 +1013,7 @@
               method_params->wait_for_ready;
         }
       }
-      grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
+      grpc_slice_hash_table_unref(exec_ctx, method_params_table);
     } else {
       gpr_mu_unlock(&chand->mu);
     }
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index bcb3082..7b64a76 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -703,7 +703,7 @@
 
 grpc_error *grpc_connected_subchannel_create_call(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
-    grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec deadline,
+    grpc_polling_entity *pollent, grpc_slice path, gpr_timespec deadline,
     grpc_subchannel_call **call) {
   grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
   *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h
index 93bd72d..17208cb 100644
--- a/src/core/ext/client_channel/subchannel.h
+++ b/src/core/ext/client_channel/subchannel.h
@@ -111,7 +111,7 @@
 /** construct a subchannel call */
 grpc_error *grpc_connected_subchannel_create_call(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
-    grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec deadline,
+    grpc_polling_entity *pollent, grpc_slice path, gpr_timespec deadline,
     grpc_subchannel_call **subchannel_call);
 
 /** process a transport level op */
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index 29ad131..37b232a 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -447,7 +447,7 @@
           GPR_ARRAY_SIZE(server->load_balance_token);
       const size_t lb_token_length =
           strnlen(server->load_balance_token, lb_token_max_length);
-      grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
+      grpc_slice lb_token_mdstr = grpc_mdstr_from_buffer(
           (uint8_t *)server->load_balance_token, lb_token_length);
       user_data = grpc_mdelem_from_metadata_strings(
           exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr);
diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.c b/src/core/ext/transport/chttp2/transport/bin_decoder.c
index 8db36e4..1a3637a 100644
--- a/src/core/ext/transport/chttp2/transport/bin_decoder.c
+++ b/src/core/ext/transport/chttp2/transport/bin_decoder.c
@@ -157,7 +157,7 @@
             "grpc_chttp2_base64_decode has a length of %d, which is not a "
             "multiple of 4.\n",
             (int)input_length);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
 
   if (input_length > 0) {
@@ -182,7 +182,7 @@
     gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
     gpr_free(s);
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
   GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
   GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input));
@@ -204,7 +204,7 @@
             "has a tail of 1 byte.\n",
             (int)input_length);
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
 
   if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
@@ -214,7 +214,7 @@
             (int)output_length,
             (int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
 
   ctx.input_cur = GRPC_SLICE_START_PTR(input);
@@ -228,7 +228,7 @@
     gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
     gpr_free(s);
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
   GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
   GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input));
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
index 3a35496..82d61a1 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -74,7 +74,7 @@
 
   /* entry tables for keys & elems: these tables track values that have been
      seen and *may* be in the decompressor table */
-  grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+  grpc_slice entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
   grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
   uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
   uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index f4e69df..3bb82fd 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -681,9 +681,9 @@
   return GRPC_ERROR_NONE;
 }
 
-static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
+static grpc_slice take_string(grpc_chttp2_hpack_parser *p,
                                grpc_chttp2_hpack_parser_string *str) {
-  grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length);
+  grpc_slice s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length);
   str->length = 0;
   return s;
 }
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index e1202e2..35609f0 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -200,7 +200,7 @@
         return err;
       }
       if (t->incoming_frame_size == 0) {
-        err = parse_frame_slice(exec_ctx, t, gpr_empty_slice(), 1);
+        err = parse_frame_slice(exec_ctx, t, grpc_empty_slice(), 1);
         if (err != GRPC_ERROR_NONE) {
           return err;
         }
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index 947dff4..30e7d65 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -162,7 +162,7 @@
     grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
     int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
     grpc_call_context_element *context, const void *transport_server_data,
-    grpc_mdstr *path, gpr_timespec deadline, grpc_call_stack *call_stack) {
+    grpc_slice path, gpr_timespec deadline, grpc_call_stack *call_stack) {
   grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
   grpc_call_element_args args;
   size_t count = channel_stack->count;
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index c3b662c..17ec027 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -74,7 +74,7 @@
   grpc_call_stack *call_stack;
   const void *server_transport_data;
   grpc_call_context_element *context;
-  grpc_mdstr *path;
+  grpc_slice path;
   gpr_timespec start_time;
   gpr_timespec deadline;
 } grpc_call_element_args;
@@ -231,7 +231,7 @@
     grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
     int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
     grpc_call_context_element *context, const void *transport_server_data,
-    grpc_mdstr *path, gpr_timespec deadline, grpc_call_stack *call_stack);
+    grpc_slice path, gpr_timespec deadline, grpc_call_stack *call_stack);
 /* Set a pollset or a pollset_set for a call stack: must occur before the first
  * op is started */
 void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index dd496ee..f58ab42 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -45,6 +45,7 @@
 #include "src/core/lib/compression/message_compress.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/transport/static_metadata.h"
 
@@ -88,21 +89,23 @@
   call_data *calld = elem->call_data;
   channel_data *channeld = elem->channel_data;
 
-  if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
-    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
-    if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
+  if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) == 0) {
+    if (!grpc_compression_algorithm_parse(md->value,
                                           &calld->compression_algorithm)) {
+      char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
       gpr_log(GPR_ERROR,
-              "Invalid compression algorithm: '%s' (unknown). Ignoring.",
-              md_c_str);
+              "Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
+      gpr_free(val);
       calld->compression_algorithm = GRPC_COMPRESS_NONE;
     }
     if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
                     calld->compression_algorithm)) {
+      char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
       gpr_log(GPR_ERROR,
               "Invalid compression algorithm: '%s' (previously disabled). "
               "Ignoring.",
-              md_c_str);
+              val);
+      gpr_free(val);
       calld->compression_algorithm = GRPC_COMPRESS_NONE;
     }
     calld->has_compression_algorithm = 1;
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 63afa4b..2ef066c 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -37,6 +37,7 @@
 #include <string.h>
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/transport_impl.h"
@@ -98,23 +99,24 @@
   client_recv_filter_args *a = user_data;
   if (md == GRPC_MDELEM_STATUS_200) {
     return NULL;
-  } else if (md->key == GRPC_MDSTR_STATUS) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_STATUS) == 0) {
     char *message_string;
-    gpr_asprintf(&message_string, "Received http2 header with status: %s",
-                 grpc_mdstr_as_c_string(md->value));
+    char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+    gpr_asprintf(&message_string, "Received http2 header with status: %s", val);
     grpc_slice message = grpc_slice_from_copied_string(message_string);
     gpr_free(message_string);
+    gpr_free(val);
     grpc_call_element_send_close_with_message(a->exec_ctx, a->elem,
                                               GRPC_STATUS_CANCELLED, &message);
     return NULL;
   } else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
     return NULL;
-  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
-    const char *value_str = grpc_mdstr_as_c_string(md->value);
-    if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
-                EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
-        (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
-         value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_CONTENT_TYPE) == 0) {
+    if (grpc_slice_buf_start_eq(md->value, EXPECTED_CONTENT_TYPE,
+                                EXPECTED_CONTENT_TYPE_LENGTH) &&
+        (GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
+         GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] ==
+             ';')) {
       /* Although the C implementation doesn't (currently) generate them,
          any custom +-suffix is explicitly valid. */
       /* TODO(klempner): We should consider preallocating common values such
@@ -123,7 +125,9 @@
     } else {
       /* TODO(klempner): We're currently allowing this, but we shouldn't
          see it without a proxy so log for now. */
-      gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
+      char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+      gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
+      gpr_free(val);
     }
     return NULL;
   }
@@ -162,11 +166,11 @@
 
 static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
   /* eat the things we'd like to set ourselves */
-  if (md->key == GRPC_MDSTR_METHOD) return NULL;
-  if (md->key == GRPC_MDSTR_SCHEME) return NULL;
-  if (md->key == GRPC_MDSTR_TE) return NULL;
-  if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
-  if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
+  if (grpc_slice_cmp(md->key, GRPC_MDSTR_METHOD) == 0) return NULL;
+  if (grpc_slice_cmp(md->key, GRPC_MDSTR_SCHEME) == 0) return NULL;
+  if (grpc_slice_cmp(md->key, GRPC_MDSTR_TE) == 0) return NULL;
+  if (grpc_slice_cmp(md->key, GRPC_MDSTR_CONTENT_TYPE) == 0) return NULL;
+  if (grpc_slice_cmp(md->key, GRPC_MDSTR_USER_AGENT) == 0) return NULL;
   return md;
 }
 
@@ -244,10 +248,10 @@
       if (calld->send_message_blocked == false) {
         /* when all the send_message data is available, then create a MDELEM and
         append to headers */
-        grpc_mdelem *payload_bin = grpc_mdelem_from_metadata_strings(
+        grpc_mdelem *payload_bin = grpc_mdelem_from_slices(
             exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN,
-            grpc_mdstr_from_buffer(calld->payload_bytes,
-                                   op->send_message->length));
+            grpc_slice_from_copied_buffer((const char *)calld->payload_bytes,
+                                          op->send_message->length));
         grpc_metadata_batch_add_tail(op->send_initial_metadata,
                                      &calld->payload_bin, payload_bin);
         calld->on_complete = op->on_complete;
@@ -338,8 +342,8 @@
       if (args->args[i].type == GRPC_ARG_STRING &&
           strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
         for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
-          if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value),
-                          args->args[i].value.string)) {
+          if (0 == grpc_slice_str_cmp(valid_schemes[j]->value,
+                                      args->args[i].value.string)) {
             return valid_schemes[j];
           }
         }
@@ -365,13 +369,13 @@
   return kMaxPayloadSizeForGet;
 }
 
-static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args,
-                                        const char *transport_name) {
+static grpc_slice user_agent_from_args(const grpc_channel_args *args,
+                                       const char *transport_name) {
   gpr_strvec v;
   size_t i;
   int is_first = 1;
   char *tmp;
-  grpc_mdstr *result;
+  grpc_slice result;
 
   gpr_strvec_init(&v);
 
@@ -409,7 +413,7 @@
 
   tmp = gpr_strvec_flatten(&v, NULL);
   gpr_strvec_destroy(&v);
-  result = grpc_mdstr_from_string(tmp);
+  result = grpc_slice_intern(grpc_slice_from_static_string(tmp));
   gpr_free(tmp);
 
   return result;
@@ -425,7 +429,7 @@
   chand->static_scheme = scheme_from_args(args->channel_args);
   chand->max_payload_size_for_get =
       max_payload_size_from_args(args->channel_args);
-  chand->user_agent = grpc_mdelem_from_metadata_strings(
+  chand->user_agent = grpc_mdelem_from_slices(
       exec_ctx, GRPC_MDSTR_USER_AGENT,
       user_agent_from_args(args->channel_args,
                            args->optional_transport->vtable->name));
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index cb0fe23..23f1a60 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -38,6 +38,7 @@
 #include <string.h>
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 #define EXPECTED_CONTENT_TYPE "application/grpc"
@@ -108,7 +109,7 @@
     } else if (md == GRPC_MDELEM_METHOD_GET) {
       calld->seen_method = 1;
       *calld->recv_cacheable_request = true;
-    } else if (md->key == GRPC_MDSTR_SCHEME) {
+    } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_SCHEME)) {
       calld->seen_scheme = 1;
     } else if (md == GRPC_MDELEM_TE_TRAILERS) {
       calld->seen_te_trailers = 1;
@@ -116,12 +117,12 @@
     /* TODO(klempner): Track that we've seen all the headers we should
        require */
     return NULL;
-  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
-    const char *value_str = grpc_mdstr_as_c_string(md->value);
-    if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
-                EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
-        (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
-         value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_CONTENT_TYPE)) {
+    if (grpc_slice_buf_start_eq(md->value, EXPECTED_CONTENT_TYPE,
+                                EXPECTED_CONTENT_TYPE_LENGTH) &&
+        (GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
+         GRPC_SLICE_START_PTR(md->value)[EXPECTED_CONTENT_TYPE_LENGTH] ==
+             ';')) {
       /* Although the C implementation doesn't (currently) generate them,
          any custom +-suffix is explicitly valid. */
       /* TODO(klempner): We should consider preallocating common values such
@@ -130,41 +131,47 @@
     } else {
       /* TODO(klempner): We're currently allowing this, but we shouldn't
          see it without a proxy so log for now. */
-      gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
+      char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+      gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
+      gpr_free(val);
     }
     return NULL;
-  } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||
-             md->key == GRPC_MDSTR_SCHEME) {
-    gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
-            grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_TE) == 0 ||
+             grpc_slice_cmp(md->key, GRPC_MDSTR_METHOD) == 0 ||
+             grpc_slice_cmp(md->key, GRPC_MDSTR_SCHEME) == 0) {
+    char *key = grpc_dump_slice(md->key, GPR_DUMP_ASCII);
+    char *value = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
+    gpr_log(GPR_ERROR, "Invalid %s: header: '%s'", key, value);
     /* swallow it and error everything out. */
     /* TODO(klempner): We ought to generate more descriptive error messages
        on the wire here. */
     grpc_call_element_send_cancel(a->exec_ctx, elem);
+    gpr_free(key);
+    gpr_free(value);
     return NULL;
-  } else if (md->key == GRPC_MDSTR_PATH) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_PATH) == 0) {
     if (calld->seen_path) {
       gpr_log(GPR_ERROR, "Received :path twice");
       return NULL;
     }
     calld->seen_path = 1;
     return md;
-  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_AUTHORITY) == 0) {
     calld->seen_authority = 1;
     return md;
-  } else if (md->key == GRPC_MDSTR_HOST) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_HOST) == 0) {
     /* translate host to :authority since :authority may be
        omitted */
-    grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
-        a->exec_ctx, GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
+    grpc_mdelem *authority = grpc_mdelem_from_slices(
+        a->exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref(md->value));
     calld->seen_authority = 1;
     return authority;
-  } else if (md->key == GRPC_MDSTR_GRPC_PAYLOAD_BIN) {
+  } else if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_PAYLOAD_BIN) == 0) {
     /* Retrieve the payload from the value of the 'grpc-internal-payload-bin'
        header field */
     calld->seen_payload_bin = 1;
     grpc_slice_buffer_add(&calld->read_slice_buffer,
-                          grpc_slice_ref_internal(md->value->slice));
+                          grpc_slice_ref_internal(md->value));
     grpc_slice_buffer_stream_init(&calld->read_stream,
                                   &calld->read_slice_buffer, 0);
     return NULL;
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 1655d84..4f61da8 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -68,7 +68,7 @@
 
 static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
 
-static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = {
+static const grpc_slice_hash_table_vtable message_size_limits_vtable = {
     free_mem, message_size_limits_copy, message_size_limits_cmp};
 
 static void* method_config_convert_value(
@@ -102,7 +102,7 @@
   int max_send_size;
   int max_recv_size;
   // Maps path names to message_size_limits structs.
-  grpc_mdstr_hash_table* method_limit_table;
+  grpc_slice_hash_table* method_limit_table;
 } channel_data;
 
 // Callback invoked when we receive a message.  Here we check the max
@@ -236,7 +236,7 @@
 static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
                                  grpc_channel_element* elem) {
   channel_data* chand = elem->channel_data;
-  grpc_mdstr_hash_table_unref(exec_ctx, chand->method_limit_table);
+  grpc_slice_hash_table_unref(exec_ctx, chand->method_limit_table);
 }
 
 const grpc_channel_filter grpc_message_size_filter = {
diff --git a/src/core/lib/compression/algorithm_metadata.h b/src/core/lib/compression/algorithm_metadata.h
index 1f9cc15..7412054 100644
--- a/src/core/lib/compression/algorithm_metadata.h
+++ b/src/core/lib/compression/algorithm_metadata.h
@@ -38,7 +38,7 @@
 #include "src/core/lib/transport/metadata.h"
 
 /** Return compression algorithm based metadata value */
-grpc_mdstr *grpc_compression_algorithm_mdstr(
+grpc_slice grpc_compression_algorithm_mdstr(
     grpc_compression_algorithm algorithm);
 
 /** Return compression algorithm based metadata element (grpc-encoding: xxx) */
@@ -48,6 +48,6 @@
 /** Find compression algorithm based on passed in mdstr - returns
  * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
 grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
-    grpc_mdstr *str);
+    grpc_slice str);
 
 #endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
diff --git a/src/core/lib/compression/compression.c b/src/core/lib/compression/compression.c
index 54efb5e..aa3caf9 100644
--- a/src/core/lib/compression/compression.c
+++ b/src/core/lib/compression/compression.c
@@ -41,30 +41,24 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/transport/static_metadata.h"
 
-int grpc_compression_algorithm_parse(const char *name, size_t name_length,
+int grpc_compression_algorithm_parse(grpc_slice name,
                                      grpc_compression_algorithm *algorithm) {
   /* we use strncmp not only because it's safer (even though in this case it
    * doesn't matter, given that we are comparing against string literals, but
    * because this way we needn't have "name" nil-terminated (useful for slice
    * data, for example) */
-  GRPC_API_TRACE(
-      "grpc_compression_algorithm_parse("
-      "name=%*.*s, name_length=%lu, algorithm=%p)",
-      5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
-          algorithm));
-  if (name_length == 0) {
-    return 0;
-  }
-  if (strncmp(name, "identity", name_length) == 0) {
+  if (grpc_slice_cmp(name, GRPC_MDSTR_IDENTITY) == 0) {
     *algorithm = GRPC_COMPRESS_NONE;
-  } else if (strncmp(name, "gzip", name_length) == 0) {
+    return 1;
+  } else if (grpc_slice_cmp(name, GRPC_MDSTR_GZIP) == 0) {
     *algorithm = GRPC_COMPRESS_GZIP;
-  } else if (strncmp(name, "deflate", name_length) == 0) {
+    return 1;
+  } else if (grpc_slice_cmp(name, GRPC_MDSTR_DEFLATE) == 0) {
     *algorithm = GRPC_COMPRESS_DEFLATE;
+    return 1;
   } else {
     return 0;
   }
-  return 1;
 }
 
 int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
@@ -88,14 +82,15 @@
 }
 
 grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
-    grpc_mdstr *str) {
-  if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
-  if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
-  if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
+    grpc_slice str) {
+  if (grpc_slice_cmp(str, GRPC_MDSTR_IDENTITY) == 0) return GRPC_COMPRESS_NONE;
+  if (grpc_slice_cmp(str, GRPC_MDSTR_DEFLATE) == 0)
+    return GRPC_COMPRESS_DEFLATE;
+  if (grpc_slice_cmp(str, GRPC_MDSTR_GZIP) == 0) return GRPC_COMPRESS_GZIP;
   return GRPC_COMPRESS_ALGORITHMS_COUNT;
 }
 
-grpc_mdstr *grpc_compression_algorithm_mdstr(
+grpc_slice grpc_compression_algorithm_mdstr(
     grpc_compression_algorithm algorithm) {
   switch (algorithm) {
     case GRPC_COMPRESS_NONE:
@@ -105,9 +100,9 @@
     case GRPC_COMPRESS_GZIP:
       return GRPC_MDSTR_GZIP;
     case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      return NULL;
+      return grpc_empty_slice();
   }
-  return NULL;
+  return grpc_empty_slice();
 }
 
 grpc_mdelem *grpc_compression_encoding_mdelem(
diff --git a/src/core/lib/iomgr/load_file.c b/src/core/lib/iomgr/load_file.c
index 217bc5d..f40c8b2 100644
--- a/src/core/lib/iomgr/load_file.c
+++ b/src/core/lib/iomgr/load_file.c
@@ -47,7 +47,7 @@
                            grpc_slice *output) {
   unsigned char *contents = NULL;
   size_t contents_size = 0;
-  grpc_slice result = gpr_empty_slice();
+  grpc_slice result = grpc_empty_slice();
   FILE *file;
   size_t bytes_read = 0;
   grpc_error *error = GRPC_ERROR_NONE;
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index 7bed78d..65eb02b 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -174,7 +174,7 @@
   grpc_auth_json_key key;
   grpc_auth_refresh_token token;
   grpc_call_credentials *result = NULL;
-  grpc_slice creds_data = gpr_empty_slice();
+  grpc_slice creds_data = grpc_empty_slice();
   grpc_error *error = GRPC_ERROR_NONE;
   if (creds_path == NULL) {
     error = GRPC_ERROR_CREATE("creds_path unset");
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index ae40bb4..e9e7718 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -54,8 +54,8 @@
 /* We can have a per-call credentials. */
 typedef struct {
   grpc_call_credentials *creds;
-  grpc_mdstr *host;
-  grpc_mdstr *method;
+  grpc_slice host;
+  grpc_slice method;
   /* pollset{_set} bound to this call; if we need to make external
      network requests, they should be done under a pollset added to this
      pollset_set so that work can progress when this call wants work to progress
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 7192f22..53bccb3 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -649,7 +649,7 @@
     ssl_server_destroy, ssl_server_check_peer};
 
 static grpc_slice compute_default_pem_root_certs_once(void) {
-  grpc_slice result = gpr_empty_slice();
+  grpc_slice result = grpc_empty_slice();
 
   /* First try to load the roots from the environment. */
   char *default_root_certs_path =
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 246ca35..1b43bdd 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -68,8 +68,8 @@
   for (l = batch->list.head; l != NULL; l = l->next) {
     grpc_metadata *usr_md = NULL;
     grpc_mdelem *md = l->md;
-    grpc_mdstr *key = md->key;
-    grpc_mdstr *value = md->value;
+    grpc_slice key = md->key;
+    grpc_slice value = md->value;
     if (result.count == result.capacity) {
       result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
       result.metadata =
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c
index bbd7e33..09c8213 100644
--- a/src/core/lib/security/util/b64.c
+++ b/src/core/lib/security/util/b64.c
@@ -232,5 +232,5 @@
 
 fail:
   grpc_slice_unref_internal(exec_ctx, result);
-  return gpr_empty_slice();
+  return grpc_empty_slice();
 }
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index 6da0952..d1f045b 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -41,7 +41,7 @@
 
 #include "src/core/lib/iomgr/exec_ctx.h"
 
-grpc_slice gpr_empty_slice(void) {
+grpc_slice grpc_empty_slice(void) {
   grpc_slice out;
   out.refcount = 0;
   out.data.inlined.length = 0;
diff --git a/src/core/lib/slice/slice_hash_table.c b/src/core/lib/slice/slice_hash_table.c
new file mode 100644
index 0000000..743a6b1
--- /dev/null
+++ b/src/core/lib/slice/slice_hash_table.c
@@ -0,0 +1,174 @@
+//
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "src/core/lib/slice/slice_hash_table.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/metadata.h"
+
+static grpc_slice_refcount terminal_slice_refcount = {0};
+static const grpc_slice terminal_slice = {&terminal_slice_refcount,
+                                          .data.refcounted = {0, 0}};
+
+struct grpc_slice_hash_table {
+  gpr_refcount refs;
+  size_t num_entries;
+  size_t size;
+  grpc_slice_hash_table_entry* entries;
+};
+
+static bool is_terminal(grpc_slice slice) {
+  return slice.refcount == &terminal_slice_refcount;
+}
+
+// Helper function for insert and get operations that performs quadratic
+// probing (https://en.wikipedia.org/wiki/Quadratic_probing).
+static size_t grpc_slice_hash_table_find_index(
+    const grpc_slice_hash_table* table, const grpc_slice key, bool find_empty) {
+  size_t hash = grpc_slice_hash(key);
+  for (size_t i = 0; i < table->size; ++i) {
+    const size_t idx = (hash + i * i) % table->size;
+    if (is_terminal(table->entries[idx].key)) {
+      return find_empty ? idx : table->size;
+    }
+    if (grpc_slice_cmp(table->entries[idx].key, key) == 0) {
+      return idx;
+    }
+  }
+  return table->size;  // Not found.
+}
+
+static void grpc_slice_hash_table_add(
+    grpc_slice_hash_table* table, grpc_slice key, void* value,
+    const grpc_slice_hash_table_vtable* vtable) {
+  GPR_ASSERT(value != NULL);
+  const size_t idx =
+      grpc_slice_hash_table_find_index(table, key, true /* find_empty */);
+  GPR_ASSERT(idx != table->size);  // Table should never be full.
+  grpc_slice_hash_table_entry* entry = &table->entries[idx];
+  entry->key = grpc_slice_ref(key);
+  entry->value = vtable->copy_value(value);
+  entry->vtable = vtable;
+}
+
+grpc_slice_hash_table* grpc_slice_hash_table_create(
+    size_t num_entries, grpc_slice_hash_table_entry* entries) {
+  grpc_slice_hash_table* table = gpr_malloc(sizeof(*table));
+  memset(table, 0, sizeof(*table));
+  gpr_ref_init(&table->refs, 1);
+  table->num_entries = num_entries;
+  // Quadratic probing gets best performance when the table is no more
+  // than half full.
+  table->size = num_entries * 2;
+  const size_t entry_size = sizeof(grpc_slice_hash_table_entry) * table->size;
+  table->entries = gpr_malloc(entry_size);
+  memset(table->entries, 0, entry_size);
+  for (size_t i = 0; i < num_entries; ++i) {
+    table->entries[i].key = terminal_slice;
+  }
+  for (size_t i = 0; i < num_entries; ++i) {
+    grpc_slice_hash_table_entry* entry = &entries[i];
+    grpc_slice_hash_table_add(table, entry->key, entry->value, entry->vtable);
+  }
+  return table;
+}
+
+grpc_slice_hash_table* grpc_slice_hash_table_ref(grpc_slice_hash_table* table) {
+  if (table != NULL) gpr_ref(&table->refs);
+  return table;
+}
+
+int grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx,
+                                grpc_slice_hash_table* table) {
+  if (table != NULL && gpr_unref(&table->refs)) {
+    for (size_t i = 0; i < table->size; ++i) {
+      grpc_slice_hash_table_entry* entry = &table->entries[i];
+      if (!is_terminal(entry->key)) {
+        grpc_slice_unref_internal(exec_ctx, entry->key);
+        entry->vtable->destroy_value(exec_ctx, entry->value);
+      }
+    }
+    gpr_free(table->entries);
+    gpr_free(table);
+    return 1;
+  }
+  return 0;
+}
+
+size_t grpc_slice_hash_table_num_entries(const grpc_slice_hash_table* table) {
+  return table->num_entries;
+}
+
+void* grpc_slice_hash_table_get(const grpc_slice_hash_table* table,
+                                const grpc_slice key) {
+  const size_t idx =
+      grpc_slice_hash_table_find_index(table, key, false /* find_empty */);
+  if (idx == table->size) return NULL;  // Not found.
+  return table->entries[idx].value;
+}
+
+int grpc_slice_hash_table_cmp(const grpc_slice_hash_table* table1,
+                              const grpc_slice_hash_table* table2) {
+  // Compare by num_entries.
+  if (table1->num_entries < table2->num_entries) return -1;
+  if (table1->num_entries > table2->num_entries) return 1;
+  for (size_t i = 0; i < table1->num_entries; ++i) {
+    grpc_slice_hash_table_entry* e1 = &table1->entries[i];
+    grpc_slice_hash_table_entry* e2 = &table2->entries[i];
+    // Compare keys by hash value.
+    int cmp = grpc_slice_cmp(e1->key, e2->key);
+    if (cmp != 0) return cmp;
+    // Compare by vtable (pointer equality).
+    if (e1->vtable < e2->vtable) return -1;
+    if (e1->vtable > e2->vtable) return 1;
+    // Compare values via vtable.
+    const int value_result = e1->vtable->compare_value(e1->value, e2->value);
+    if (value_result != 0) return value_result;
+  }
+  return 0;
+}
+
+void grpc_slice_hash_table_iterate(
+    const grpc_slice_hash_table* table,
+    void (*func)(const grpc_slice_hash_table_entry* entry, void* user_data),
+    void* user_data) {
+  for (size_t i = 0; i < table->size; ++i) {
+    if (!is_terminal(table->entries[i].key)) {
+      func(&table->entries[i], user_data);
+    }
+  }
+}
diff --git a/src/core/lib/transport/mdstr_hash_table.h b/src/core/lib/slice/slice_hash_table.h
similarity index 66%
rename from src/core/lib/transport/mdstr_hash_table.h
rename to src/core/lib/slice/slice_hash_table.h
index 45e5720..ac04950 100644
--- a/src/core/lib/transport/mdstr_hash_table.h
+++ b/src/core/lib/slice/slice_hash_table.h
@@ -40,54 +40,54 @@
  * (https://en.wikipedia.org/wiki/Open_addressing) with quadratic
  * probing (https://en.wikipedia.org/wiki/Quadratic_probing).
  *
- * The keys are \a grpc_mdstr objects.  The values are arbitrary pointers
+ * The keys are \a grpc_slice objects.  The values are arbitrary pointers
  * with a common vtable.
  *
  * Hash tables are intentionally immutable, to avoid the need for locking.
  */
 
-typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table;
+typedef struct grpc_slice_hash_table grpc_slice_hash_table;
 
-typedef struct grpc_mdstr_hash_table_vtable {
-  void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value);
-  void* (*copy_value)(void* value);
-  int (*compare_value)(void* value1, void* value2);
-} grpc_mdstr_hash_table_vtable;
+typedef struct grpc_slice_hash_table_vtable {
+  void (*destroy_value)(grpc_exec_ctx *exec_ctx, void *value);
+  void *(*copy_value)(void *value);
+  int (*compare_value)(void *value1, void *value2);
+} grpc_slice_hash_table_vtable;
 
-typedef struct grpc_mdstr_hash_table_entry {
-  grpc_mdstr* key;
-  void* value; /* Must not be NULL. */
-  const grpc_mdstr_hash_table_vtable* vtable;
-} grpc_mdstr_hash_table_entry;
+typedef struct grpc_slice_hash_table_entry {
+  grpc_slice key;
+  void *value; /* Must not be NULL. */
+  const grpc_slice_hash_table_vtable *vtable;
+} grpc_slice_hash_table_entry;
 
 /** Creates a new hash table of containing \a entries, which is an array
     of length \a num_entries.
     Creates its own copy of all keys and values from \a entries. */
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
-    size_t num_entries, grpc_mdstr_hash_table_entry* entries);
+grpc_slice_hash_table *grpc_slice_hash_table_create(
+    size_t num_entries, grpc_slice_hash_table_entry *entries);
 
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
+grpc_slice_hash_table *grpc_slice_hash_table_ref(grpc_slice_hash_table *table);
 /** Returns 1 when \a table is destroyed. */
-int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
-                                grpc_mdstr_hash_table* table);
+int grpc_slice_hash_table_unref(grpc_exec_ctx *exec_ctx,
+                                grpc_slice_hash_table *table);
 
 /** Returns the number of entries in \a table. */
-size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table);
+size_t grpc_slice_hash_table_num_entries(const grpc_slice_hash_table *table);
 
 /** Returns the value from \a table associated with \a key.
     Returns NULL if \a key is not found. */
-void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
-                                const grpc_mdstr* key);
+void *grpc_slice_hash_table_get(const grpc_slice_hash_table *table,
+                                const grpc_slice key);
 
 /** Compares two hash tables.
     The sort order is stable but undefined. */
-int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
-                              const grpc_mdstr_hash_table* table2);
+int grpc_slice_hash_table_cmp(const grpc_slice_hash_table *table1,
+                              const grpc_slice_hash_table *table2);
 
 /** Iterates over the entries in \a table, calling \a func for each entry. */
-void grpc_mdstr_hash_table_iterate(
-    const grpc_mdstr_hash_table* table,
-    void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
-    void* user_data);
+void grpc_slice_hash_table_iterate(
+    const grpc_slice_hash_table *table,
+    void (*func)(const grpc_slice_hash_table_entry *entry, void *user_data),
+    void *user_data);
 
 #endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 9be13d8..f826d32 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -94,7 +94,7 @@
 typedef struct {
   uint8_t is_set;
   grpc_status_code code;
-  grpc_mdstr *details;
+  grpc_slice details;
 } received_status;
 
 typedef struct batch_control {
@@ -244,7 +244,7 @@
   /* Always support no compression */
   GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
   call->is_client = args->server_transport_data == NULL;
-  grpc_mdstr *path = NULL;
+  grpc_slice path = NULL;
   if (call->is_client) {
     GPR_ASSERT(args->add_initial_metadata_count <
                MAX_SEND_EXTRA_METADATA_COUNT);
@@ -443,7 +443,7 @@
 }
 
 static void set_status_details(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                               status_source source, grpc_mdstr *status) {
+                               status_source source, grpc_slice status) {
   if (call->status[source].details != NULL) {
     GRPC_MDSTR_UNREF(exec_ctx, status);
   } else {
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 530e5ed..8f0cfbb 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -98,8 +98,8 @@
 typedef struct channel_registered_method {
   registered_method *server_registered_method;
   uint32_t flags;
-  grpc_mdstr *method;
-  grpc_mdstr *host;
+  grpc_slice method;
+  grpc_slice host;
 } channel_registered_method;
 
 struct channel_data {
@@ -144,8 +144,8 @@
   /** the current state of a call - see call_state */
   call_state state;
 
-  grpc_mdstr *path;
-  grpc_mdstr *host;
+  grpc_slice path;
+  grpc_slice host;
   gpr_timespec deadline;
 
   grpc_completion_queue *cq_new;
@@ -459,7 +459,7 @@
                        op);
 }
 
-static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
+static void cpstr(char **dest, size_t *capacity, grpc_slice value) {
   grpc_slice slice = value->slice;
   size_t len = GRPC_SLICE_LENGTH(slice);
 
@@ -1136,8 +1136,8 @@
   channel_registered_method *crm;
   grpc_channel *channel;
   channel_data *chand;
-  grpc_mdstr *host;
-  grpc_mdstr *method;
+  grpc_slice host;
+  grpc_slice method;
   uint32_t hash;
   size_t slots;
   uint32_t probes;
diff --git a/src/core/lib/transport/mdstr_hash_table.c b/src/core/lib/transport/mdstr_hash_table.c
deleted file mode 100644
index a3f6bde..0000000
--- a/src/core/lib/transport/mdstr_hash_table.c
+++ /dev/null
@@ -1,158 +0,0 @@
-//
-// Copyright 2016, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "src/core/lib/transport/mdstr_hash_table.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/lib/transport/metadata.h"
-
-struct grpc_mdstr_hash_table {
-  gpr_refcount refs;
-  size_t num_entries;
-  size_t size;
-  grpc_mdstr_hash_table_entry* entries;
-};
-
-// Helper function for insert and get operations that performs quadratic
-// probing (https://en.wikipedia.org/wiki/Quadratic_probing).
-static size_t grpc_mdstr_hash_table_find_index(
-    const grpc_mdstr_hash_table* table, const grpc_mdstr* key,
-    bool find_empty) {
-  for (size_t i = 0; i < table->size; ++i) {
-    const size_t idx = (key->hash + i * i) % table->size;
-    if (table->entries[idx].key == NULL) return find_empty ? idx : table->size;
-    if (table->entries[idx].key == key) return idx;
-  }
-  return table->size;  // Not found.
-}
-
-static void grpc_mdstr_hash_table_add(
-    grpc_mdstr_hash_table* table, grpc_mdstr* key, void* value,
-    const grpc_mdstr_hash_table_vtable* vtable) {
-  GPR_ASSERT(value != NULL);
-  const size_t idx =
-      grpc_mdstr_hash_table_find_index(table, key, true /* find_empty */);
-  GPR_ASSERT(idx != table->size);  // Table should never be full.
-  grpc_mdstr_hash_table_entry* entry = &table->entries[idx];
-  entry->key = GRPC_MDSTR_REF(key);
-  entry->value = vtable->copy_value(value);
-  entry->vtable = vtable;
-}
-
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
-    size_t num_entries, grpc_mdstr_hash_table_entry* entries) {
-  grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table));
-  memset(table, 0, sizeof(*table));
-  gpr_ref_init(&table->refs, 1);
-  table->num_entries = num_entries;
-  // Quadratic probing gets best performance when the table is no more
-  // than half full.
-  table->size = num_entries * 2;
-  const size_t entry_size = sizeof(grpc_mdstr_hash_table_entry) * table->size;
-  table->entries = gpr_malloc(entry_size);
-  memset(table->entries, 0, entry_size);
-  for (size_t i = 0; i < num_entries; ++i) {
-    grpc_mdstr_hash_table_entry* entry = &entries[i];
-    grpc_mdstr_hash_table_add(table, entry->key, entry->value, entry->vtable);
-  }
-  return table;
-}
-
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
-  if (table != NULL) gpr_ref(&table->refs);
-  return table;
-}
-
-int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
-                                grpc_mdstr_hash_table* table) {
-  if (table != NULL && gpr_unref(&table->refs)) {
-    for (size_t i = 0; i < table->size; ++i) {
-      grpc_mdstr_hash_table_entry* entry = &table->entries[i];
-      if (entry->key != NULL) {
-        GRPC_MDSTR_UNREF(exec_ctx, entry->key);
-        entry->vtable->destroy_value(exec_ctx, entry->value);
-      }
-    }
-    gpr_free(table->entries);
-    gpr_free(table);
-    return 1;
-  }
-  return 0;
-}
-
-size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table) {
-  return table->num_entries;
-}
-
-void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
-                                const grpc_mdstr* key) {
-  const size_t idx =
-      grpc_mdstr_hash_table_find_index(table, key, false /* find_empty */);
-  if (idx == table->size) return NULL;  // Not found.
-  return table->entries[idx].value;
-}
-
-int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
-                              const grpc_mdstr_hash_table* table2) {
-  // Compare by num_entries.
-  if (table1->num_entries < table2->num_entries) return -1;
-  if (table1->num_entries > table2->num_entries) return 1;
-  for (size_t i = 0; i < table1->num_entries; ++i) {
-    grpc_mdstr_hash_table_entry* e1 = &table1->entries[i];
-    grpc_mdstr_hash_table_entry* e2 = &table2->entries[i];
-    // Compare keys by hash value.
-    if (e1->key->hash < e2->key->hash) return -1;
-    if (e1->key->hash > e2->key->hash) return 1;
-    // Compare by vtable (pointer equality).
-    if (e1->vtable < e2->vtable) return -1;
-    if (e1->vtable > e2->vtable) return 1;
-    // Compare values via vtable.
-    const int value_result = e1->vtable->compare_value(e1->value, e2->value);
-    if (value_result != 0) return value_result;
-  }
-  return 0;
-}
-
-void grpc_mdstr_hash_table_iterate(
-    const grpc_mdstr_hash_table* table,
-    void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
-    void* user_data) {
-  for (size_t i = 0; i < table->size; ++i) {
-    if (table->entries[i].key != NULL) {
-      func(&table->entries[i], user_data);
-    }
-  }
-}
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index c0743e1..fd6c52c 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -137,7 +137,7 @@
   memset(g_static_mdtab, 0, sizeof(g_static_mdtab));
   memset(g_static_strtab, 0, sizeof(g_static_strtab));
   for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
-    grpc_mdstr *elem = &grpc_static_mdstr_table[i];
+    grpc_slice elem = &grpc_static_mdstr_table[i];
     const char *str = grpc_static_metadata_strings[i];
     uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed);
     *(grpc_slice *)&elem->slice = grpc_slice_from_static_string(str);
@@ -155,13 +155,13 @@
   }
   for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
     grpc_mdelem *elem = &grpc_static_mdelem_table[i];
-    grpc_mdstr *key =
+    grpc_slice key =
         &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]];
-    grpc_mdstr *value =
+    grpc_slice value =
         &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]];
     uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash);
-    *(grpc_mdstr **)&elem->key = key;
-    *(grpc_mdstr **)&elem->value = value;
+    *(grpc_slice *)&elem->key = key;
+    *(grpc_slice *)&elem->value = value;
     for (j = 0;; j++) {
       size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab);
       if (g_static_mdtab[idx] == NULL) {
@@ -216,8 +216,8 @@
           "ELM   REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
           gpr_atm_no_barrier_load(&md->refcnt),
           gpr_atm_no_barrier_load(&md->refcnt) + 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+          grpc_mdstr_as_c_string((grpc_slice)md->key),
+          grpc_mdstr_as_c_string((grpc_slice)md->value));
 #endif
   if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
     gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1);
@@ -351,8 +351,8 @@
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
   gpr_log(GPR_DEBUG, "ELM   NEW:%p:%zu: '%s' = '%s'", (void *)md,
           gpr_atm_no_barrier_load(&md->refcnt),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+          grpc_mdstr_as_c_string((grpc_slice)md->key),
+          grpc_mdstr_as_c_string((grpc_slice)md->value));
 #endif
   shard->count++;
 
@@ -391,8 +391,8 @@
           "ELM   REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
           gpr_atm_no_barrier_load(&md->refcnt),
           gpr_atm_no_barrier_load(&md->refcnt) + 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+          grpc_mdstr_as_c_string((grpc_slice)md->key),
+          grpc_mdstr_as_c_string((grpc_slice)md->value));
 #endif
   /* we can assume the ref count is >= 1 as the application is calling
      this function - meaning that no adjustment to mdtab_free is necessary,
@@ -412,8 +412,8 @@
           "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
           gpr_atm_no_barrier_load(&md->refcnt),
           gpr_atm_no_barrier_load(&md->refcnt) - 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+          grpc_mdstr_as_c_string((grpc_slice)md->key),
+          grpc_mdstr_as_c_string((grpc_slice)md->value));
 #endif
   uint32_t hash =
       GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), grpc_slice_hash(md->value));
diff --git a/src/core/lib/transport/method_config.c b/src/core/lib/transport/method_config.c
index 25fb54b..0b3a6c8 100644
--- a/src/core/lib/transport/method_config.c
+++ b/src/core/lib/transport/method_config.c
@@ -39,7 +39,7 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 
-#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/slice/slice_hash_table.h"
 #include "src/core/lib/transport/metadata.h"
 
 //
@@ -65,7 +65,7 @@
 
 static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
 
-static grpc_mdstr_hash_table_vtable bool_vtable = {free_mem, bool_copy,
+static grpc_slice_hash_table_vtable bool_vtable = {free_mem, bool_copy,
                                                    bool_cmp};
 
 // timespec vtable
@@ -81,7 +81,7 @@
   return gpr_time_cmp(*(gpr_timespec*)v1, *(gpr_timespec*)v2);
 }
 
-static grpc_mdstr_hash_table_vtable timespec_vtable = {free_mem, timespec_copy,
+static grpc_slice_hash_table_vtable timespec_vtable = {free_mem, timespec_copy,
                                                        timespec_cmp};
 
 // int32 vtable
@@ -101,7 +101,7 @@
   return 0;
 }
 
-static grpc_mdstr_hash_table_vtable int32_vtable = {free_mem, int32_copy,
+static grpc_slice_hash_table_vtable int32_vtable = {free_mem, int32_copy,
                                                     int32_cmp};
 
 // Hash table keys.
@@ -113,11 +113,11 @@
   "grpc.max_response_message_bytes"  // int32
 
 struct grpc_method_config {
-  grpc_mdstr_hash_table* table;
-  grpc_mdstr* wait_for_ready_key;
-  grpc_mdstr* timeout_key;
-  grpc_mdstr* max_request_message_bytes_key;
-  grpc_mdstr* max_response_message_bytes_key;
+  grpc_slice_hash_table* table;
+  grpc_slice  wait_for_ready_key;
+  grpc_slice  timeout_key;
+  grpc_slice  max_request_message_bytes_key;
+  grpc_slice  max_response_message_bytes_key;
 };
 
 grpc_method_config* grpc_method_config_create(
@@ -133,7 +133,7 @@
       grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES);
   method_config->max_response_message_bytes_key =
       grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES);
-  grpc_mdstr_hash_table_entry entries[4];
+  grpc_slice_hash_table_entry entries[4];
   size_t num_entries = 0;
   if (wait_for_ready != NULL) {
     entries[num_entries].key = method_config->wait_for_ready_key;
@@ -159,18 +159,18 @@
     entries[num_entries].vtable = &int32_vtable;
     ++num_entries;
   }
-  method_config->table = grpc_mdstr_hash_table_create(num_entries, entries);
+  method_config->table = grpc_slice_hash_table_create(num_entries, entries);
   return method_config;
 }
 
 grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) {
-  grpc_mdstr_hash_table_ref(method_config->table);
+  grpc_slice_hash_table_ref(method_config->table);
   return method_config;
 }
 
 void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
                               grpc_method_config* method_config) {
-  if (grpc_mdstr_hash_table_unref(exec_ctx, method_config->table)) {
+  if (grpc_slice_hash_table_unref(exec_ctx, method_config->table)) {
     GRPC_MDSTR_UNREF(exec_ctx, method_config->wait_for_ready_key);
     GRPC_MDSTR_UNREF(exec_ctx, method_config->timeout_key);
     GRPC_MDSTR_UNREF(exec_ctx, method_config->max_request_message_bytes_key);
@@ -181,31 +181,31 @@
 
 int grpc_method_config_cmp(const grpc_method_config* method_config1,
                            const grpc_method_config* method_config2) {
-  return grpc_mdstr_hash_table_cmp(method_config1->table,
+  return grpc_slice_hash_table_cmp(method_config1->table,
                                    method_config2->table);
 }
 
 const bool* grpc_method_config_get_wait_for_ready(
     const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(method_config->table,
+  return grpc_slice_hash_table_get(method_config->table,
                                    method_config->wait_for_ready_key);
 }
 
 const gpr_timespec* grpc_method_config_get_timeout(
     const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(method_config->table,
+  return grpc_slice_hash_table_get(method_config->table,
                                    method_config->timeout_key);
 }
 
 const int32_t* grpc_method_config_get_max_request_message_bytes(
     const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(
+  return grpc_slice_hash_table_get(
       method_config->table, method_config->max_request_message_bytes_key);
 }
 
 const int32_t* grpc_method_config_get_max_response_message_bytes(
     const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(
+  return grpc_slice_hash_table_get(
       method_config->table, method_config->max_response_message_bytes_key);
 }
 
@@ -225,43 +225,43 @@
   return grpc_method_config_cmp(valuep1, valuep2);
 }
 
-static const grpc_mdstr_hash_table_vtable method_config_table_vtable = {
+static const grpc_slice_hash_table_vtable method_config_table_vtable = {
     method_config_unref, method_config_ref, method_config_cmp};
 
 grpc_method_config_table* grpc_method_config_table_create(
     size_t num_entries, grpc_method_config_table_entry* entries) {
-  grpc_mdstr_hash_table_entry* hash_table_entries =
-      gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * num_entries);
+  grpc_slice_hash_table_entry* hash_table_entries =
+      gpr_malloc(sizeof(grpc_slice_hash_table_entry) * num_entries);
   for (size_t i = 0; i < num_entries; ++i) {
     hash_table_entries[i].key = entries[i].method_name;
     hash_table_entries[i].value = entries[i].method_config;
     hash_table_entries[i].vtable = &method_config_table_vtable;
   }
   grpc_method_config_table* method_config_table =
-      grpc_mdstr_hash_table_create(num_entries, hash_table_entries);
+      grpc_slice_hash_table_create(num_entries, hash_table_entries);
   gpr_free(hash_table_entries);
   return method_config_table;
 }
 
 grpc_method_config_table* grpc_method_config_table_ref(
     grpc_method_config_table* table) {
-  return grpc_mdstr_hash_table_ref(table);
+  return grpc_slice_hash_table_ref(table);
 }
 
 void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
                                     grpc_method_config_table* table) {
-  grpc_mdstr_hash_table_unref(exec_ctx, table);
+  grpc_slice_hash_table_unref(exec_ctx, table);
 }
 
 int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
                                  const grpc_method_config_table* table2) {
-  return grpc_mdstr_hash_table_cmp(table1, table2);
+  return grpc_slice_hash_table_cmp(table1, table2);
 }
 
 void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
-                                   const grpc_mdstr_hash_table* table,
-                                   const grpc_mdstr* path) {
-  void* value = grpc_mdstr_hash_table_get(table, path);
+                                   const grpc_slice_hash_table* table,
+                                   const grpc_slice  path) {
+  void* value = grpc_slice_hash_table_get(table, path);
   // If we didn't find a match for the path, try looking for a wildcard
   // entry (i.e., change "/service/method" to "/service/*").
   if (value == NULL) {
@@ -272,9 +272,9 @@
     memcpy(buf, path_str, len);
     buf[len] = '*';
     buf[len + 1] = '\0';
-    grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
+    grpc_slice  wildcard_path = grpc_mdstr_from_string(buf);
     gpr_free(buf);
-    value = grpc_mdstr_hash_table_get(table, wildcard_path);
+    value = grpc_slice_hash_table_get(table, wildcard_path);
     GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
   }
   return value;
@@ -305,14 +305,14 @@
 // State used by convert_entry() below.
 typedef struct conversion_state {
   void* (*convert_value)(const grpc_method_config* method_config);
-  const grpc_mdstr_hash_table_vtable* vtable;
+  const grpc_slice_hash_table_vtable* vtable;
   size_t num_entries;
-  grpc_mdstr_hash_table_entry* entries;
+  grpc_slice_hash_table_entry* entries;
 } conversion_state;
 
-// A function to be passed to grpc_mdstr_hash_table_iterate() to create
+// A function to be passed to grpc_slice_hash_table_iterate() to create
 // a copy of the entries.
-static void convert_entry(const grpc_mdstr_hash_table_entry* entry,
+static void convert_entry(const grpc_slice_hash_table_entry* entry,
                           void* user_data) {
   conversion_state* state = user_data;
   state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key);
@@ -321,21 +321,21 @@
   ++state->num_entries;
 }
 
-grpc_mdstr_hash_table* grpc_method_config_table_convert(
+grpc_slice_hash_table* grpc_method_config_table_convert(
     grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table,
     void* (*convert_value)(const grpc_method_config* method_config),
-    const grpc_mdstr_hash_table_vtable* vtable) {
+    const grpc_slice_hash_table_vtable* vtable) {
   // Create an array of the entries in the table with converted values.
   conversion_state state;
   state.convert_value = convert_value;
   state.vtable = vtable;
   state.num_entries = 0;
-  state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) *
-                             grpc_mdstr_hash_table_num_entries(table));
-  grpc_mdstr_hash_table_iterate(table, convert_entry, &state);
+  state.entries = gpr_malloc(sizeof(grpc_slice_hash_table_entry) *
+                             grpc_slice_hash_table_num_entries(table));
+  grpc_slice_hash_table_iterate(table, convert_entry, &state);
   // Create a new table based on the array we just constructed.
-  grpc_mdstr_hash_table* new_table =
-      grpc_mdstr_hash_table_create(state.num_entries, state.entries);
+  grpc_slice_hash_table* new_table =
+      grpc_slice_hash_table_create(state.num_entries, state.entries);
   // Clean up the array.
   for (size_t i = 0; i < state.num_entries; ++i) {
     GRPC_MDSTR_UNREF(exec_ctx, state.entries[i].key);
diff --git a/src/core/lib/transport/method_config.h b/src/core/lib/transport/method_config.h
index d17a493..3e266a6 100644
--- a/src/core/lib/transport/method_config.h
+++ b/src/core/lib/transport/method_config.h
@@ -37,7 +37,7 @@
 #include <grpc/impl/codegen/gpr_types.h>
 #include <grpc/impl/codegen/grpc_types.h>
 
-#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/slice/slice_hash_table.h"
 #include "src/core/lib/transport/metadata.h"
 
 /// Per-method configuration.
@@ -55,70 +55,70 @@
 /// \a max_request_message_bytes and \a max_response_message_bytes
 /// indicate the maximum sizes of the request (checked when sending) and
 /// response (checked when receiving) messages.
-grpc_method_config* grpc_method_config_create(
-    bool* wait_for_ready, gpr_timespec* timeout,
-    int32_t* max_request_message_bytes, int32_t* max_response_message_bytes);
+grpc_method_config *grpc_method_config_create(
+    bool *wait_for_ready, gpr_timespec *timeout,
+    int32_t *max_request_message_bytes, int32_t *max_response_message_bytes);
 
-grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config);
-void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
-                              grpc_method_config* method_config);
+grpc_method_config *grpc_method_config_ref(grpc_method_config *method_config);
+void grpc_method_config_unref(grpc_exec_ctx *exec_ctx,
+                              grpc_method_config *method_config);
 
 /// Compares two grpc_method_configs.
 /// The sort order is stable but undefined.
-int grpc_method_config_cmp(const grpc_method_config* method_config1,
-                           const grpc_method_config* method_config2);
+int grpc_method_config_cmp(const grpc_method_config *method_config1,
+                           const grpc_method_config *method_config2);
 
 /// These methods return NULL if the requested field is unset.
 /// The caller does NOT take ownership of the result.
-const bool* grpc_method_config_get_wait_for_ready(
-    const grpc_method_config* method_config);
-const gpr_timespec* grpc_method_config_get_timeout(
-    const grpc_method_config* method_config);
-const int32_t* grpc_method_config_get_max_request_message_bytes(
-    const grpc_method_config* method_config);
-const int32_t* grpc_method_config_get_max_response_message_bytes(
-    const grpc_method_config* method_config);
+const bool *grpc_method_config_get_wait_for_ready(
+    const grpc_method_config *method_config);
+const gpr_timespec *grpc_method_config_get_timeout(
+    const grpc_method_config *method_config);
+const int32_t *grpc_method_config_get_max_request_message_bytes(
+    const grpc_method_config *method_config);
+const int32_t *grpc_method_config_get_max_response_message_bytes(
+    const grpc_method_config *method_config);
 
 /// A table of method configs.
-typedef grpc_mdstr_hash_table grpc_method_config_table;
+typedef grpc_slice_hash_table grpc_method_config_table;
 
 typedef struct grpc_method_config_table_entry {
   /// The name is of one of the following forms:
   ///   service/method -- specifies exact service and method name
   ///   service/*      -- matches all methods for the specified service
-  grpc_mdstr* method_name;
-  grpc_method_config* method_config;
+  grpc_slice method_name;
+  grpc_method_config *method_config;
 } grpc_method_config_table_entry;
 
 /// Takes new references to all keys and values in \a entries.
-grpc_method_config_table* grpc_method_config_table_create(
-    size_t num_entries, grpc_method_config_table_entry* entries);
+grpc_method_config_table *grpc_method_config_table_create(
+    size_t num_entries, grpc_method_config_table_entry *entries);
 
-grpc_method_config_table* grpc_method_config_table_ref(
-    grpc_method_config_table* table);
-void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
-                                    grpc_method_config_table* table);
+grpc_method_config_table *grpc_method_config_table_ref(
+    grpc_method_config_table *table);
+void grpc_method_config_table_unref(grpc_exec_ctx *exec_ctx,
+                                    grpc_method_config_table *table);
 
 /// Compares two grpc_method_config_tables.
 /// The sort order is stable but undefined.
-int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
-                                 const grpc_method_config_table* table2);
+int grpc_method_config_table_cmp(const grpc_method_config_table *table1,
+                                 const grpc_method_config_table *table2);
 
 /// Gets the method config for the specified \a path, which should be of
 /// the form "/service/method".
 /// Returns NULL if the method has no config.
 /// Caller does NOT own a reference to the result.
 ///
-/// Note: This returns a void* instead of a grpc_method_config* so that
+/// Note: This returns a void *instead of a grpc_method_config *so that
 /// it can also be used for tables constructed via
 /// grpc_method_config_table_convert().
-void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
-                                   const grpc_mdstr_hash_table* table,
-                                   const grpc_mdstr* path);
+void *grpc_method_config_table_get(grpc_exec_ctx *exec_ctx,
+                                   const grpc_slice_hash_table *table,
+                                   const grpc_slice path);
 
 /// Returns a channel arg containing \a table.
 grpc_arg grpc_method_config_table_create_channel_arg(
-    grpc_method_config_table* table);
+    grpc_method_config_table *table);
 
 /// Generates a new table from \a table whose values are converted to a
 /// new form via the \a convert_value function.  The new table will use
@@ -131,9 +131,9 @@
 /// will return a new instance of the struct containing the values from
 /// the grpc_method_config, and \a vtable provides the methods for
 /// operating on the struct type.
-grpc_mdstr_hash_table* grpc_method_config_table_convert(
-    grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table,
-    void* (*convert_value)(const grpc_method_config* method_config),
-    const grpc_mdstr_hash_table_vtable* vtable);
+grpc_slice_hash_table *grpc_method_config_table_convert(
+    grpc_exec_ctx *exec_ctx, const grpc_method_config_table *table,
+    void *(*convert_value)(const grpc_method_config *method_config),
+    const grpc_slice_hash_table_vtable *vtable);
 
 #endif /* GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H */
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index dccac39..cbe721f 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -47,192 +47,192 @@
 #define GRPC_STATIC_MDSTR_COUNT 93
 extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
 /* "0" */
-#define GRPC_MDSTR_0 (&grpc_static_slice_table[0])
+#define GRPC_MDSTR_0 (grpc_static_slice_table[0])
 /* "1" */
-#define GRPC_MDSTR_1 (&grpc_static_slice_table[1])
+#define GRPC_MDSTR_1 (grpc_static_slice_table[1])
 /* "2" */
-#define GRPC_MDSTR_2 (&grpc_static_slice_table[2])
+#define GRPC_MDSTR_2 (grpc_static_slice_table[2])
 /* "200" */
-#define GRPC_MDSTR_200 (&grpc_static_slice_table[3])
+#define GRPC_MDSTR_200 (grpc_static_slice_table[3])
 /* "204" */
-#define GRPC_MDSTR_204 (&grpc_static_slice_table[4])
+#define GRPC_MDSTR_204 (grpc_static_slice_table[4])
 /* "206" */
-#define GRPC_MDSTR_206 (&grpc_static_slice_table[5])
+#define GRPC_MDSTR_206 (grpc_static_slice_table[5])
 /* "304" */
-#define GRPC_MDSTR_304 (&grpc_static_slice_table[6])
+#define GRPC_MDSTR_304 (grpc_static_slice_table[6])
 /* "400" */
-#define GRPC_MDSTR_400 (&grpc_static_slice_table[7])
+#define GRPC_MDSTR_400 (grpc_static_slice_table[7])
 /* "404" */
-#define GRPC_MDSTR_404 (&grpc_static_slice_table[8])
+#define GRPC_MDSTR_404 (grpc_static_slice_table[8])
 /* "500" */
-#define GRPC_MDSTR_500 (&grpc_static_slice_table[9])
+#define GRPC_MDSTR_500 (grpc_static_slice_table[9])
 /* "accept" */
-#define GRPC_MDSTR_ACCEPT (&grpc_static_slice_table[10])
+#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[10])
 /* "accept-charset" */
-#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_slice_table[11])
+#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[11])
 /* "accept-encoding" */
-#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_slice_table[12])
+#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[12])
 /* "accept-language" */
-#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_slice_table[13])
+#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[13])
 /* "accept-ranges" */
-#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_slice_table[14])
+#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[14])
 /* "access-control-allow-origin" */
-#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_slice_table[15])
+#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[15])
 /* "age" */
-#define GRPC_MDSTR_AGE (&grpc_static_slice_table[16])
+#define GRPC_MDSTR_AGE (grpc_static_slice_table[16])
 /* "allow" */
-#define GRPC_MDSTR_ALLOW (&grpc_static_slice_table[17])
+#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[17])
 /* "application/grpc" */
-#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (&grpc_static_slice_table[18])
+#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[18])
 /* ":authority" */
-#define GRPC_MDSTR_AUTHORITY (&grpc_static_slice_table[19])
+#define GRPC_MDSTR_AUTHORITY (grpc_static_slice_table[19])
 /* "authorization" */
-#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_slice_table[20])
+#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[20])
 /* "cache-control" */
-#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_slice_table[21])
+#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[21])
 /* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_slice_table[22])
+#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[22])
 /* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_slice_table[23])
+#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[23])
 /* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_slice_table[24])
+#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[24])
 /* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_slice_table[25])
+#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[25])
 /* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_slice_table[26])
+#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[26])
 /* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_slice_table[27])
+#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[27])
 /* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_slice_table[28])
+#define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table[28])
 /* "cookie" */
-#define GRPC_MDSTR_COOKIE (&grpc_static_slice_table[29])
+#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[29])
 /* "date" */
-#define GRPC_MDSTR_DATE (&grpc_static_slice_table[30])
+#define GRPC_MDSTR_DATE (grpc_static_slice_table[30])
 /* "deflate" */
-#define GRPC_MDSTR_DEFLATE (&grpc_static_slice_table[31])
+#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[31])
 /* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_slice_table[32])
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[32])
 /* "" */
-#define GRPC_MDSTR_EMPTY (&grpc_static_slice_table[33])
+#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[33])
 /* "etag" */
-#define GRPC_MDSTR_ETAG (&grpc_static_slice_table[34])
+#define GRPC_MDSTR_ETAG (grpc_static_slice_table[34])
 /* "expect" */
-#define GRPC_MDSTR_EXPECT (&grpc_static_slice_table[35])
+#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[35])
 /* "expires" */
-#define GRPC_MDSTR_EXPIRES (&grpc_static_slice_table[36])
+#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[36])
 /* "from" */
-#define GRPC_MDSTR_FROM (&grpc_static_slice_table[37])
+#define GRPC_MDSTR_FROM (grpc_static_slice_table[37])
 /* "GET" */
-#define GRPC_MDSTR_GET (&grpc_static_slice_table[38])
+#define GRPC_MDSTR_GET (grpc_static_slice_table[38])
 /* "grpc" */
-#define GRPC_MDSTR_GRPC (&grpc_static_slice_table[39])
+#define GRPC_MDSTR_GRPC (grpc_static_slice_table[39])
 /* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_slice_table[40])
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (grpc_static_slice_table[40])
 /* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_slice_table[41])
+#define GRPC_MDSTR_GRPC_ENCODING (grpc_static_slice_table[41])
 /* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_slice_table[42])
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[42])
 /* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_slice_table[43])
+#define GRPC_MDSTR_GRPC_MESSAGE (grpc_static_slice_table[43])
 /* "grpc-payload-bin" */
-#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (&grpc_static_slice_table[44])
+#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (grpc_static_slice_table[44])
 /* "grpc-stats-bin" */
-#define GRPC_MDSTR_GRPC_STATS_BIN (&grpc_static_slice_table[45])
+#define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[45])
 /* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_slice_table[46])
+#define GRPC_MDSTR_GRPC_STATUS (grpc_static_slice_table[46])
 /* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_slice_table[47])
+#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[47])
 /* "grpc-tracing-bin" */
-#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_slice_table[48])
+#define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[48])
 /* "gzip" */
-#define GRPC_MDSTR_GZIP (&grpc_static_slice_table[49])
+#define GRPC_MDSTR_GZIP (grpc_static_slice_table[49])
 /* "gzip, deflate" */
-#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_slice_table[50])
+#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[50])
 /* "host" */
-#define GRPC_MDSTR_HOST (&grpc_static_slice_table[51])
+#define GRPC_MDSTR_HOST (grpc_static_slice_table[51])
 /* "http" */
-#define GRPC_MDSTR_HTTP (&grpc_static_slice_table[52])
+#define GRPC_MDSTR_HTTP (grpc_static_slice_table[52])
 /* "https" */
-#define GRPC_MDSTR_HTTPS (&grpc_static_slice_table[53])
+#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[53])
 /* "identity" */
-#define GRPC_MDSTR_IDENTITY (&grpc_static_slice_table[54])
+#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[54])
 /* "identity,deflate" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (&grpc_static_slice_table[55])
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[55])
 /* "identity,deflate,gzip" */
 #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (&grpc_static_slice_table[56])
+  (grpc_static_slice_table[56])
 /* "identity,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (&grpc_static_slice_table[57])
+#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[57])
 /* "if-match" */
-#define GRPC_MDSTR_IF_MATCH (&grpc_static_slice_table[58])
+#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[58])
 /* "if-modified-since" */
-#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_slice_table[59])
+#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[59])
 /* "if-none-match" */
-#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_slice_table[60])
+#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[60])
 /* "if-range" */
-#define GRPC_MDSTR_IF_RANGE (&grpc_static_slice_table[61])
+#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[61])
 /* "if-unmodified-since" */
-#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_slice_table[62])
+#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[62])
 /* "last-modified" */
-#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_slice_table[63])
+#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[63])
 /* "lb-cost-bin" */
-#define GRPC_MDSTR_LB_COST_BIN (&grpc_static_slice_table[64])
+#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[64])
 /* "lb-token" */
-#define GRPC_MDSTR_LB_TOKEN (&grpc_static_slice_table[65])
+#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[65])
 /* "link" */
-#define GRPC_MDSTR_LINK (&grpc_static_slice_table[66])
+#define GRPC_MDSTR_LINK (grpc_static_slice_table[66])
 /* "location" */
-#define GRPC_MDSTR_LOCATION (&grpc_static_slice_table[67])
+#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[67])
 /* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_slice_table[68])
+#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[68])
 /* ":method" */
-#define GRPC_MDSTR_METHOD (&grpc_static_slice_table[69])
+#define GRPC_MDSTR_METHOD (grpc_static_slice_table[69])
 /* ":path" */
-#define GRPC_MDSTR_PATH (&grpc_static_slice_table[70])
+#define GRPC_MDSTR_PATH (grpc_static_slice_table[70])
 /* "POST" */
-#define GRPC_MDSTR_POST (&grpc_static_slice_table[71])
+#define GRPC_MDSTR_POST (grpc_static_slice_table[71])
 /* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_slice_table[72])
+#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[72])
 /* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_slice_table[73])
+#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[73])
 /* "PUT" */
-#define GRPC_MDSTR_PUT (&grpc_static_slice_table[74])
+#define GRPC_MDSTR_PUT (grpc_static_slice_table[74])
 /* "range" */
-#define GRPC_MDSTR_RANGE (&grpc_static_slice_table[75])
+#define GRPC_MDSTR_RANGE (grpc_static_slice_table[75])
 /* "referer" */
-#define GRPC_MDSTR_REFERER (&grpc_static_slice_table[76])
+#define GRPC_MDSTR_REFERER (grpc_static_slice_table[76])
 /* "refresh" */
-#define GRPC_MDSTR_REFRESH (&grpc_static_slice_table[77])
+#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[77])
 /* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_slice_table[78])
+#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[78])
 /* ":scheme" */
-#define GRPC_MDSTR_SCHEME (&grpc_static_slice_table[79])
+#define GRPC_MDSTR_SCHEME (grpc_static_slice_table[79])
 /* "server" */
-#define GRPC_MDSTR_SERVER (&grpc_static_slice_table[80])
+#define GRPC_MDSTR_SERVER (grpc_static_slice_table[80])
 /* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (&grpc_static_slice_table[81])
+#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[81])
 /* "/" */
-#define GRPC_MDSTR_SLASH (&grpc_static_slice_table[82])
+#define GRPC_MDSTR_SLASH (grpc_static_slice_table[82])
 /* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_slice_table[83])
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[83])
 /* ":status" */
-#define GRPC_MDSTR_STATUS (&grpc_static_slice_table[84])
+#define GRPC_MDSTR_STATUS (grpc_static_slice_table[84])
 /* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_slice_table[85])
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[85])
 /* "te" */
-#define GRPC_MDSTR_TE (&grpc_static_slice_table[86])
+#define GRPC_MDSTR_TE (grpc_static_slice_table[86])
 /* "trailers" */
-#define GRPC_MDSTR_TRAILERS (&grpc_static_slice_table[87])
+#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[87])
 /* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_slice_table[88])
+#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[88])
 /* "user-agent" */
-#define GRPC_MDSTR_USER_AGENT (&grpc_static_slice_table[89])
+#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[89])
 /* "vary" */
-#define GRPC_MDSTR_VARY (&grpc_static_slice_table[90])
+#define GRPC_MDSTR_VARY (grpc_static_slice_table[90])
 /* "via" */
-#define GRPC_MDSTR_VIA (&grpc_static_slice_table[91])
+#define GRPC_MDSTR_VIA (grpc_static_slice_table[91])
 /* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_slice_table[92])
+#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[92])
 
 bool grpc_is_static_metadata_string(grpc_slice slice);
 
diff --git a/src/cpp/util/slice_cc.cc b/src/cpp/util/slice_cc.cc
index c05f1cf..6efb68e 100644
--- a/src/cpp/util/slice_cc.cc
+++ b/src/cpp/util/slice_cc.cc
@@ -35,7 +35,7 @@
 
 namespace grpc {
 
-Slice::Slice() : slice_(gpr_empty_slice()) {}
+Slice::Slice() : slice_(grpc_empty_slice()) {}
 
 Slice::~Slice() { grpc_slice_unref(slice_); }
 
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index c0d6bba..44967fe 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -157,6 +157,7 @@
   'src/core/lib/slice/percent_encoding.c',
   'src/core/lib/slice/slice.c',
   'src/core/lib/slice/slice_buffer.c',
+  'src/core/lib/slice/slice_hash_table.c',
   'src/core/lib/slice/slice_intern.c',
   'src/core/lib/slice/slice_string_helpers.c',
   'src/core/lib/surface/alarm.c',
@@ -179,7 +180,6 @@
   'src/core/lib/surface/version.c',
   'src/core/lib/transport/byte_stream.c',
   'src/core/lib/transport/connectivity_state.c',
-  'src/core/lib/transport/mdstr_hash_table.c',
   'src/core/lib/transport/metadata.c',
   'src/core/lib/transport/metadata_batch.c',
   'src/core/lib/transport/method_config.c',
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index b8c7eef..ada6ef1 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -187,9 +187,12 @@
 grpc_slice_sub_no_ref_type grpc_slice_sub_no_ref_import;
 grpc_slice_split_tail_type grpc_slice_split_tail_import;
 grpc_slice_split_head_type grpc_slice_split_head_import;
-gpr_empty_slice_type gpr_empty_slice_import;
+grpc_empty_slice_type grpc_empty_slice_import;
 grpc_slice_cmp_type grpc_slice_cmp_import;
 grpc_slice_str_cmp_type grpc_slice_str_cmp_import;
+grpc_slice_buf_cmp_type grpc_slice_buf_cmp_import;
+grpc_slice_buf_start_eq_type grpc_slice_buf_start_eq_import;
+grpc_slice_hash_type grpc_slice_hash_import;
 grpc_slice_buffer_init_type grpc_slice_buffer_init_import;
 grpc_slice_buffer_destroy_type grpc_slice_buffer_destroy_import;
 grpc_slice_buffer_add_type grpc_slice_buffer_add_import;
@@ -463,9 +466,12 @@
   grpc_slice_sub_no_ref_import = (grpc_slice_sub_no_ref_type) GetProcAddress(library, "grpc_slice_sub_no_ref");
   grpc_slice_split_tail_import = (grpc_slice_split_tail_type) GetProcAddress(library, "grpc_slice_split_tail");
   grpc_slice_split_head_import = (grpc_slice_split_head_type) GetProcAddress(library, "grpc_slice_split_head");
-  gpr_empty_slice_import = (gpr_empty_slice_type) GetProcAddress(library, "gpr_empty_slice");
+  grpc_empty_slice_import = (grpc_empty_slice_type) GetProcAddress(library, "grpc_empty_slice");
   grpc_slice_cmp_import = (grpc_slice_cmp_type) GetProcAddress(library, "grpc_slice_cmp");
   grpc_slice_str_cmp_import = (grpc_slice_str_cmp_type) GetProcAddress(library, "grpc_slice_str_cmp");
+  grpc_slice_buf_cmp_import = (grpc_slice_buf_cmp_type) GetProcAddress(library, "grpc_slice_buf_cmp");
+  grpc_slice_buf_start_eq_import = (grpc_slice_buf_start_eq_type) GetProcAddress(library, "grpc_slice_buf_start_eq");
+  grpc_slice_hash_import = (grpc_slice_hash_type) GetProcAddress(library, "grpc_slice_hash");
   grpc_slice_buffer_init_import = (grpc_slice_buffer_init_type) GetProcAddress(library, "grpc_slice_buffer_init");
   grpc_slice_buffer_destroy_import = (grpc_slice_buffer_destroy_type) GetProcAddress(library, "grpc_slice_buffer_destroy");
   grpc_slice_buffer_add_import = (grpc_slice_buffer_add_type) GetProcAddress(library, "grpc_slice_buffer_add");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index ba436dd..3d14e88 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -176,7 +176,7 @@
 typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues);
 extern census_record_values_type census_record_values_import;
 #define census_record_values census_record_values_import
-typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm);
+typedef int(*grpc_compression_algorithm_parse_type)(grpc_slice value, grpc_compression_algorithm *algorithm);
 extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
 #define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import
 typedef int(*grpc_compression_algorithm_name_type)(grpc_compression_algorithm algorithm, char **name);
@@ -512,15 +512,24 @@
 typedef grpc_slice(*grpc_slice_split_head_type)(grpc_slice *s, size_t split);
 extern grpc_slice_split_head_type grpc_slice_split_head_import;
 #define grpc_slice_split_head grpc_slice_split_head_import
-typedef grpc_slice(*gpr_empty_slice_type)(void);
-extern gpr_empty_slice_type gpr_empty_slice_import;
-#define gpr_empty_slice gpr_empty_slice_import
+typedef grpc_slice(*grpc_empty_slice_type)(void);
+extern grpc_empty_slice_type grpc_empty_slice_import;
+#define grpc_empty_slice grpc_empty_slice_import
 typedef int(*grpc_slice_cmp_type)(grpc_slice a, grpc_slice b);
 extern grpc_slice_cmp_type grpc_slice_cmp_import;
 #define grpc_slice_cmp grpc_slice_cmp_import
 typedef int(*grpc_slice_str_cmp_type)(grpc_slice a, const char *b);
 extern grpc_slice_str_cmp_type grpc_slice_str_cmp_import;
 #define grpc_slice_str_cmp grpc_slice_str_cmp_import
+typedef int(*grpc_slice_buf_cmp_type)(grpc_slice a, const void *b, size_t blen);
+extern grpc_slice_buf_cmp_type grpc_slice_buf_cmp_import;
+#define grpc_slice_buf_cmp grpc_slice_buf_cmp_import
+typedef int(*grpc_slice_buf_start_eq_type)(grpc_slice a, const void *b, size_t blen);
+extern grpc_slice_buf_start_eq_type grpc_slice_buf_start_eq_import;
+#define grpc_slice_buf_start_eq grpc_slice_buf_start_eq_import
+typedef uint32_t(*grpc_slice_hash_type)(grpc_slice s);
+extern grpc_slice_hash_type grpc_slice_hash_import;
+#define grpc_slice_hash grpc_slice_hash_import
 typedef void(*grpc_slice_buffer_init_type)(grpc_slice_buffer *sb);
 extern grpc_slice_buffer_init_type grpc_slice_buffer_init_import;
 #define grpc_slice_buffer_init grpc_slice_buffer_init_import
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index 388bdc6..f0c6ffe 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -287,7 +287,7 @@
 print >>H, 'extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];'
 for i, elem in enumerate(all_strs):
   print >>H, '/* "%s" */' % elem
-  print >>H, '#define %s (&grpc_static_slice_table[%d])' % (mangle(elem).upper(), i)
+  print >>H, '#define %s (grpc_static_slice_table[%d])' % (mangle(elem).upper(), i)
 print >>H
 print >>H, 'bool grpc_is_static_metadata_string(grpc_slice slice);'
 print >>H
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 25ec70e..a79b1e1 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -863,6 +863,7 @@
 src/core/lib/json/json_reader.h \
 src/core/lib/json/json_writer.h \
 src/core/lib/slice/percent_encoding.h \
+src/core/lib/slice/slice_hash_table.h \
 src/core/lib/slice/slice_string_helpers.h \
 src/core/lib/surface/api_trace.h \
 src/core/lib/surface/call.h \
@@ -877,7 +878,6 @@
 src/core/lib/surface/server.h \
 src/core/lib/transport/byte_stream.h \
 src/core/lib/transport/connectivity_state.h \
-src/core/lib/transport/mdstr_hash_table.h \
 src/core/lib/transport/metadata.h \
 src/core/lib/transport/metadata_batch.h \
 src/core/lib/transport/method_config.h \
@@ -1049,6 +1049,7 @@
 src/core/lib/slice/percent_encoding.c \
 src/core/lib/slice/slice.c \
 src/core/lib/slice/slice_buffer.c \
+src/core/lib/slice/slice_hash_table.c \
 src/core/lib/slice/slice_intern.c \
 src/core/lib/slice/slice_string_helpers.c \
 src/core/lib/surface/alarm.c \
@@ -1071,7 +1072,6 @@
 src/core/lib/surface/version.c \
 src/core/lib/transport/byte_stream.c \
 src/core/lib/transport/connectivity_state.c \
-src/core/lib/transport/mdstr_hash_table.c \
 src/core/lib/transport/metadata.c \
 src/core/lib/transport/metadata_batch.c \
 src/core/lib/transport/method_config.c \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index a3c2091..4ab990b 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -6689,6 +6689,7 @@
       "src/core/lib/json/json_reader.h", 
       "src/core/lib/json/json_writer.h", 
       "src/core/lib/slice/percent_encoding.h", 
+      "src/core/lib/slice/slice_hash_table.h", 
       "src/core/lib/slice/slice_string_helpers.h", 
       "src/core/lib/surface/api_trace.h", 
       "src/core/lib/surface/call.h", 
@@ -6703,7 +6704,6 @@
       "src/core/lib/surface/server.h", 
       "src/core/lib/transport/byte_stream.h", 
       "src/core/lib/transport/connectivity_state.h", 
-      "src/core/lib/transport/mdstr_hash_table.h", 
       "src/core/lib/transport/metadata.h", 
       "src/core/lib/transport/metadata_batch.h", 
       "src/core/lib/transport/method_config.h", 
@@ -6882,6 +6882,8 @@
       "src/core/lib/slice/percent_encoding.h", 
       "src/core/lib/slice/slice.c", 
       "src/core/lib/slice/slice_buffer.c", 
+      "src/core/lib/slice/slice_hash_table.c", 
+      "src/core/lib/slice/slice_hash_table.h", 
       "src/core/lib/slice/slice_intern.c", 
       "src/core/lib/slice/slice_string_helpers.c", 
       "src/core/lib/slice/slice_string_helpers.h", 
@@ -6918,8 +6920,6 @@
       "src/core/lib/transport/byte_stream.h", 
       "src/core/lib/transport/connectivity_state.c", 
       "src/core/lib/transport/connectivity_state.h", 
-      "src/core/lib/transport/mdstr_hash_table.c", 
-      "src/core/lib/transport/mdstr_hash_table.h", 
       "src/core/lib/transport/metadata.c", 
       "src/core/lib/transport/metadata.h", 
       "src/core/lib/transport/metadata_batch.c", 
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index f0e061f..85bcfbe 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -372,6 +372,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
@@ -386,7 +387,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
@@ -643,6 +643,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
@@ -687,8 +689,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 8809da1..c0ec86c 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -250,6 +250,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -316,9 +319,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
-      <Filter>src\core\lib\transport</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
@@ -956,6 +956,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
@@ -998,9 +1001,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 2e19a14..38c4d82 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -265,6 +265,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
@@ -279,7 +280,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
@@ -494,6 +494,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
@@ -538,8 +540,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index e66da7b..0e3bd1d 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -307,6 +307,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -373,9 +376,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
-      <Filter>src\core\lib\transport</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
@@ -752,6 +752,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
@@ -794,9 +797,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 55604c5..efd474a 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -362,6 +362,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
@@ -376,7 +377,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
@@ -611,6 +611,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
@@ -655,8 +657,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 69c52cc..aa19a2a 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -253,6 +253,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -319,9 +322,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
-      <Filter>src\core\lib\transport</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
@@ -869,6 +869,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
@@ -911,9 +914,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
-      <Filter>src\core\lib\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>