|  | @@ -51,6 +51,7 @@
 | 
	
		
			
				|  |  |  #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/arena.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/support/string.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/surface/api_trace.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/surface/call.h"
 | 
	
	
		
			
				|  | @@ -138,6 +139,7 @@ typedef struct batch_control {
 | 
	
		
			
				|  |  |  } batch_control;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct grpc_call {
 | 
	
		
			
				|  |  | +  gpr_arena *arena;
 | 
	
		
			
				|  |  |    grpc_completion_queue *cq;
 | 
	
		
			
				|  |  |    grpc_polling_entity pollent;
 | 
	
		
			
				|  |  |    grpc_channel *channel;
 | 
	
	
		
			
				|  | @@ -212,6 +214,8 @@ struct grpc_call {
 | 
	
		
			
				|  |  |    grpc_closure receiving_initial_metadata_ready;
 | 
	
		
			
				|  |  |    uint32_t test_only_last_message_flags;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  grpc_closure release_call;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    union {
 | 
	
		
			
				|  |  |      struct {
 | 
	
		
			
				|  |  |        grpc_status_code *status;
 | 
	
	
		
			
				|  | @@ -273,7 +277,10 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |        grpc_channel_get_channel_stack(args->channel);
 | 
	
		
			
				|  |  |    grpc_call *call;
 | 
	
		
			
				|  |  |    GPR_TIMER_BEGIN("grpc_call_create", 0);
 | 
	
		
			
				|  |  | -  call = gpr_zalloc(sizeof(grpc_call) + channel_stack->call_stack_size);
 | 
	
		
			
				|  |  | +  gpr_arena *arena = gpr_arena_create(8192);
 | 
	
		
			
				|  |  | +  call = gpr_arena_alloc(arena,
 | 
	
		
			
				|  |  | +                         sizeof(grpc_call) + channel_stack->call_stack_size);
 | 
	
		
			
				|  |  | +  call->arena = arena;
 | 
	
		
			
				|  |  |    *out_call = call;
 | 
	
		
			
				|  |  |    gpr_mu_init(&call->mu);
 | 
	
		
			
				|  |  |    call->channel = args->channel;
 | 
	
	
		
			
				|  | @@ -421,6 +428,13 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
 | 
	
		
			
				|  |  |    GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void release_call(grpc_exec_ctx *exec_ctx, void *call,
 | 
	
		
			
				|  |  | +                         grpc_error *error) {
 | 
	
		
			
				|  |  | +  grpc_call *c = call;
 | 
	
		
			
				|  |  | +  gpr_arena_destroy(c->arena);
 | 
	
		
			
				|  |  | +  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->channel, "call");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void set_status_value_directly(grpc_status_code status, void *dest);
 | 
	
		
			
				|  |  |  static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
 | 
	
		
			
				|  |  |                           grpc_error *error) {
 | 
	
	
		
			
				|  | @@ -447,7 +461,6 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
 | 
	
		
			
				|  |  |    if (c->cq) {
 | 
	
		
			
				|  |  |      GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  grpc_channel *channel = c->channel;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    get_final_status(call, set_status_value_directly, &c->final_info.final_status,
 | 
	
		
			
				|  |  |                     NULL);
 | 
	
	
		
			
				|  | @@ -459,8 +472,9 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
 | 
	
		
			
				|  |  |          unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
 | 
	
		
			
				|  |  | -  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
 | 
	
		
			
				|  |  | +  grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info,
 | 
	
		
			
				|  |  | +                          grpc_closure_init(&c->release_call, release_call, c,
 | 
	
		
			
				|  |  | +                                            grpc_schedule_on_exec_ctx));
 | 
	
		
			
				|  |  |    GPR_TIMER_END("destroy_call", 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |