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 »