Bug #13085 » 0001-io.c-recycle-garbage-on-write.patch
| internal.h | ||
|---|---|---|
| char *rb_str_fill_terminator(VALUE str, const int termlen); | ||
| void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen); | ||
| VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg); | ||
| VALUE rb_str_tmp_frozen_acquire(VALUE str); | ||
| void rb_str_tmp_frozen_release(VALUE str, VALUE tmp); | ||
| VALUE rb_str_chomp_string(VALUE str, VALUE chomp); | ||
| #ifdef RUBY_ENCODING_H | ||
| VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc); | ||
| io.c | ||
|---|---|---|
|     return str; | ||
| } | ||
| struct fwrite_arg { | ||
|     VALUE orig; | ||
|     VALUE tmp; | ||
|     rb_io_t *fptr; | ||
|     int nosync; | ||
| }; | ||
| static VALUE | ||
| fwrite_do(VALUE arg) | ||
| { | ||
|     struct fwrite_arg *fa = (struct fwrite_arg *)arg; | ||
|     const char *ptr; | ||
|     long len; | ||
|     RSTRING_GETMEM(fa->tmp, ptr, len); | ||
|     return (VALUE)io_binwrite(fa->tmp, ptr, len, fa->fptr, fa->nosync); | ||
| } | ||
| static VALUE | ||
| fwrite_end(VALUE arg) | ||
| { | ||
|     struct fwrite_arg *fa = (struct fwrite_arg *)arg; | ||
|     rb_str_tmp_frozen_release(fa->orig, fa->tmp); | ||
|     return Qfalse; | ||
| } | ||
| static long | ||
| io_fwrite(VALUE str, rb_io_t *fptr, int nosync) | ||
| { | ||
|     int converted = 0; | ||
|     struct fwrite_arg fa; | ||
| #ifdef _WIN32 | ||
|     if (fptr->mode & FMODE_TTY) { | ||
| 	long len = rb_w32_write_console(str, fptr->fd); | ||
| ... | ... | |
|     str = do_writeconv(str, fptr, &converted); | ||
|     if (converted) | ||
| 	OBJ_FREEZE(str); | ||
|     else | ||
| 	str = rb_str_new_frozen(str); | ||
|     return io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), | ||
| 		       fptr, nosync); | ||
|     fa.orig = str; | ||
|     fa.tmp = rb_str_tmp_frozen_acquire(str); | ||
|     fa.fptr = fptr; | ||
|     fa.nosync = nosync; | ||
|     return (long)rb_ensure(fwrite_do, (VALUE)&fa, fwrite_end, (VALUE)&fa); | ||
| } | ||
| ssize_t | ||
| string.c | ||
|---|---|---|
|  * 1:     RSTRING_NOEMBED | ||
|  * 2:     STR_SHARED (== ELTS_SHARED) | ||
|  * 2-6:   RSTRING_EMBED_LEN (5 bits == 32) | ||
|  * 6:     STR_IS_SHARED_M (shared, when RSTRING_NOEMBED==1 && klass==0) | ||
|  * 7:     STR_TMPLOCK | ||
|  * 8-9:   ENC_CODERANGE (2 bits) | ||
|  * 10-16: ENCODING (7 bits == 128) | ||
| ... | ... | |
|  */ | ||
| #define RUBY_MAX_CHAR_LEN 16 | ||
| #define STR_IS_SHARED_M FL_USER6 | ||
| #define STR_TMPLOCK FL_USER7 | ||
| #define STR_NOFREE FL_USER18 | ||
| #define STR_FAKESTR FL_USER19 | ||
| ... | ... | |
|     if (!FL_TEST(str, STR_FAKESTR)) { \ | ||
| 	RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \ | ||
| 	FL_SET((str), STR_SHARED); \ | ||
| 	if (RBASIC_CLASS((shared_str)) == 0) /* for CoW-friendliness */ \ | ||
| 	    FL_SET_RAW((shared_str), STR_IS_SHARED_M); \ | ||
|     } \ | ||
| } while (0) | ||
| ... | ... | |
|     return str; | ||
| } | ||
| VALUE | ||
| rb_str_tmp_frozen_acquire(VALUE orig) | ||
| { | ||
|     VALUE tmp; | ||
|     if (OBJ_FROZEN_RAW(orig)) return orig; | ||
|     tmp = str_new_frozen(0, orig); | ||
|     OBJ_INFECT(tmp, orig); | ||
|     return tmp; | ||
| } | ||
| void | ||
| rb_str_tmp_frozen_release(VALUE orig, VALUE tmp) | ||
| { | ||
|     if (RBASIC_CLASS(tmp) != 0) | ||
| 	return; | ||
|     if (FL_TEST_RAW(orig, STR_SHARED) && | ||
| 	    !FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)) { | ||
| 	VALUE shared = RSTRING(orig)->as.heap.aux.shared; | ||
| 	if (shared == tmp && !FL_TEST_RAW(tmp, STR_IS_SHARED_M)) { | ||
| 	    FL_UNSET_RAW(orig, STR_SHARED); | ||
| 	    assert(RSTRING(orig)->as.heap.ptr == RSTRING(tmp)->as.heap.ptr); | ||
| 	    assert(RSTRING(orig)->as.heap.len == RSTRING(tmp)->as.heap.len); | ||
| 	    RSTRING(orig)->as.heap.aux.capa = RSTRING(tmp)->as.heap.aux.capa; | ||
| 	    RBASIC(orig)->flags |= RBASIC(tmp)->flags & STR_NOFREE; | ||
| 	    assert(OBJ_FROZEN_RAW(tmp)); | ||
| 	    rb_gc_force_recycle(tmp); | ||
| 	} | ||
|     } | ||
|     else if (STR_EMBED_P(tmp)) { | ||
| 	assert(OBJ_FROZEN_RAW(tmp)); | ||
| 	rb_gc_force_recycle(tmp); | ||
|     } | ||
| } | ||
| static VALUE | ||
| str_new_frozen(VALUE klass, VALUE orig) | ||
| { | ||
| ... | ... | |
| 		RSTRING(str)->as.heap.len -= ofs + rest; | ||
| 	    } | ||
| 	    else { | ||
| 		if (RBASIC_CLASS(shared) == 0) | ||
| 		    FL_SET_RAW(shared, STR_IS_SHARED_M); | ||
| 		return shared; | ||
| 	    } | ||
| 	} | ||
| ... | ... | |
| 	    RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE; | ||
| 	    RBASIC(orig)->flags &= ~STR_NOFREE; | ||
| 	    STR_SET_SHARED(orig, str); | ||
| 	    if (klass == 0) | ||
| 		FL_UNSET_RAW(str, STR_IS_SHARED_M); | ||
| 	} | ||
|     } | ||
| -  | ||
- « Previous
- 1
- 2
- 3
- 4
- Next »