Project

General

Profile

Feature #14315 ยป 0001-zlib-reduce-garbage-on-gzip-writes-deflate.patch

normalperson (Eric Wong), 01/05/2018 11:20 AM

View differences:

ext/zlib/zlib.c
845 845
static void
846 846
zstream_discard_input(struct zstream *z, long len)
847 847
{
848
    if (NIL_P(z->input) || RSTRING_LEN(z->input) <= len) {
849
	z->input = Qnil;
848
    if (NIL_P(z->input)) {
850 849
    }
851
    else {
852
	z->input = rb_str_substr(z->input, len,
853
				 RSTRING_LEN(z->input) - len);
850
    else if (RBASIC_CLASS(z->input) == 0) {
851
	/* hidden, we created z->input and have complete control */
852
	char *ptr;
853
	long oldlen, newlen;
854

  
855
	RSTRING_GETMEM(z->input, ptr, oldlen);
856
	newlen = oldlen - len;
857
	if (newlen > 0) {
858
	    memmove(ptr, ptr + len, newlen);
859
	}
860
	if (newlen < 0) {
861
	    newlen = 0;
862
	}
863
	rb_str_resize(z->input, newlen);
864
	if (newlen == 0) {
865
	    rb_gc_force_recycle(z->input);
866
	    z->input = Qnil;
867
	}
868
	else {
869
	    rb_str_set_len(z->input, newlen);
870
	}
871
    }
872
    else { /* do not mangle user-provided data */
873
	if (RSTRING_LEN(z->input) <= len) {
874
	    z->input = Qnil;
875
	}
876
	else {
877
	    z->input = rb_str_substr(z->input, len,
878
				     RSTRING_LEN(z->input) - len);
879
	}
854 880
    }
855 881
}
856 882

  
857 883
static void
858 884
zstream_reset_input(struct zstream *z)
859 885
{
860
    z->input = Qnil;
886
    if (!NIL_P(z->input) && RBASIC_CLASS(z->input) == 0) {
887
	rb_str_resize(z->input, 0);
888
    }
889
    else {
890
	z->input = Qnil;
891
    }
861 892
}
862 893

  
863 894
static void
......
994 1025
{
995 1026
    struct zstream_run_args args;
996 1027
    int err;
997
    VALUE guard = Qnil;
1028
    VALUE old_input = Qnil;
998 1029

  
999 1030
    args.z = z;
1000 1031
    args.flush = flush;
......
1013 1044
	/* keep reference to `z->input' so as not to be garbage collected
1014 1045
	   after zstream_reset_input() and prevent `z->stream.next_in'
1015 1046
	   from dangling. */
1016
	guard = z->input;
1047
	old_input = zstream_detach_input(z);
1048
	rb_obj_hide(old_input);
1017 1049
    }
1018 1050

  
1019 1051
    if (z->stream.avail_out == 0) {
......
1051 1083

  
1052 1084
    if (z->stream.avail_in > 0) {
1053 1085
	zstream_append_input(z, z->stream.next_in, z->stream.avail_in);
1054
	RB_GC_GUARD(guard); /* prevent tail call to make guard effective */
1086
    }
1087
    if (!NIL_P(old_input)) {
1088
	rb_str_resize(old_input, 0);
1089
	rb_gc_force_recycle(old_input);
1055 1090
    }
1056 1091

  
1057 1092
    if (args.jump_state)
......
2330 2365
	str = zstream_detach_buffer(&gz->z);
2331 2366
	OBJ_TAINT(str);  /* for safe */
2332 2367
	rb_funcall(gz->io, id_write, 1, str);
2368
	rb_str_resize(str, 0);
2333 2369
	if ((gz->z.flags & GZFILE_FLAG_SYNC)
2334 2370
	    && rb_respond_to(gz->io, id_flush))
2335 2371
	    rb_funcall(gz->io, id_flush, 0);
2336
-