| 
					
				 | 
			
			
				@@ -48,6 +48,20 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define INITIAL_STRTAB_CAPACITY 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define INITIAL_MDTAB_CAPACITY 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEBUG_ARGS , const char *file, int line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define FWD_DEBUG_ARGS , file, line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define INTERNAL_STRING_REF(s) internal_string_ref((s), __FILE__, __LINE__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define INTERNAL_STRING_UNREF(s) internal_string_unref((s), __FILE__, __LINE__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define REF_MD_LOCKED(s) ref_md_locked((s), __FILE__, __LINE__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define DEBUG_ARGS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define FWD_DEBUG_ARGS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define INTERNAL_STRING_REF(s) internal_string_ref((s)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define INTERNAL_STRING_UNREF(s) internal_string_unref((s)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define REF_MD_LOCKED(s) ref_md_locked((s)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct internal_string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* must be byte compatible with grpc_mdstr */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_slice slice; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -96,8 +110,8 @@ struct grpc_mdctx { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t mdtab_capacity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void internal_string_ref(internal_string *s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void internal_string_unref(internal_string *s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void internal_string_ref(internal_string *s DEBUG_ARGS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void internal_string_unref(internal_string *s DEBUG_ARGS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void discard_metadata(grpc_mdctx *ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void gc_mdtab(grpc_mdctx *ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void metadata_context_destroy_locked(grpc_mdctx *ctx); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -132,7 +146,15 @@ static void unlock(grpc_mdctx *ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&ctx->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void ref_md_locked(internal_metadata *md) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void ref_md_locked(internal_metadata *md DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "ELM   REF:%p:%d->%d: '%s' = '%s'", 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)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     md->context->mdtab_free--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -173,8 +195,8 @@ static void discard_metadata(grpc_mdctx *ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while (cur) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       next = cur->bucket_next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      internal_string_unref(cur->key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      internal_string_unref(cur->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      INTERNAL_STRING_UNREF(cur->key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      INTERNAL_STRING_UNREF(cur->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (cur->user_data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         cur->destroy_user_data(cur->user_data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -248,9 +270,19 @@ static void internal_destroy_string(internal_string *is) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void internal_string_ref(internal_string *s) { ++s->refs; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void internal_string_ref(internal_string *s DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR   REF:%p:%d->%d: '%s'", s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          s->refs, s->refs + 1, grpc_mdstr_as_c_string((grpc_mdstr *)s)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ++s->refs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void internal_string_unref(internal_string *s) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void internal_string_unref(internal_string *s DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR UNREF:%p:%d->%d: '%s'", s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          s->refs, s->refs - 1, grpc_mdstr_as_c_string((grpc_mdstr *)s)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(s->refs > 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (0 == --s->refs) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     internal_destroy_string(s); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -262,7 +294,7 @@ static void slice_ref(void *p) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (internal_string *)((char *)p - offsetof(internal_string, refcount)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_mdctx *ctx = is->context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   lock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  internal_string_ref(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  INTERNAL_STRING_REF(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unlock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -271,7 +303,7 @@ static void slice_unref(void *p) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (internal_string *)((char *)p - offsetof(internal_string, refcount)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_mdctx *ctx = is->context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   lock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  internal_string_unref(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  INTERNAL_STRING_UNREF(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unlock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -297,7 +329,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *buf, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (s = ctx->strtab[hash % ctx->strtab_capacity]; s; s = s->bucket_next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      internal_string_ref(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      INTERNAL_STRING_REF(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       unlock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return (grpc_mdstr *)s; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -353,8 +385,8 @@ static void gc_mdtab(grpc_mdctx *ctx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (md = ctx->mdtab[i]; md; md = next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       next = md->bucket_next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (gpr_atm_acq_load(&md->refcnt) == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        internal_string_unref(md->key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        internal_string_unref(md->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        INTERNAL_STRING_UNREF(md->key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        INTERNAL_STRING_UNREF(md->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (md->user_data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           md->destroy_user_data(md->user_data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -418,9 +450,9 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* search for an existing pair */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (md = ctx->mdtab[hash % ctx->mdtab_capacity]; md; md = md->bucket_next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (md->key == key && md->value == value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      ref_md_locked(md); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      internal_string_unref(key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      internal_string_unref(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      REF_MD_LOCKED(md); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      INTERNAL_STRING_UNREF(key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      INTERNAL_STRING_UNREF(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       unlock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return (grpc_mdelem *)md; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -435,6 +467,12 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   md->user_data = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   md->destroy_user_data = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(GPR_DEBUG, "ELM   NEW:%p:%d: '%s' = '%s'", 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)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ctx->mdtab[hash % ctx->mdtab_capacity] = md; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ctx->mdtab_count++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -469,8 +507,16 @@ grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_mdstr_from_buffer(ctx, value, value_length)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   internal_metadata *md = (internal_metadata *)gmd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "ELM   REF:%p:%d->%d: '%s' = '%s'", 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)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#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, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      simplifying the logic here to be just an atomic increment */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -480,10 +526,18 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return gmd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void grpc_mdelem_unref(grpc_mdelem *gmd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   internal_metadata *md = (internal_metadata *)gmd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_mdctx *ctx = md->context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   lock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "ELM UNREF:%p:%d->%d: '%s' = '%s'", 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)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ctx->mdtab_free++; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -495,20 +549,20 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return (const char *)GPR_SLICE_START_PTR(s->slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   internal_string *s = (internal_string *)gs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_mdctx *ctx = s->context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   lock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  internal_string_ref(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  internal_string_ref(s FWD_DEBUG_ARGS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unlock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return gs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void grpc_mdstr_unref(grpc_mdstr *gs) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   internal_string *s = (internal_string *)gs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_mdctx *ctx = s->context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   lock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  internal_string_unref(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  internal_string_unref(s FWD_DEBUG_ARGS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unlock(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -558,10 +612,19 @@ gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void grpc_mdctx_lock(grpc_mdctx *ctx) { lock(ctx); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *gmd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    grpc_mdelem *gmd DEBUG_ARGS) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   internal_metadata *md = (internal_metadata *)gmd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_mdctx *elem_ctx = md->context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(ctx == elem_ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef GRPC_METADATA_REFCOUNT_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "ELM UNREF:%p:%d->%d: '%s' = '%s'", 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)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ctx->mdtab_free++; 
			 |