Project

General

Profile

Feature #10182 » mvm-fstring.patch

nobu (Nobuyoshi Nakada), 08/29/2014 08:39 AM

View differences:

w/eval.c
Init_BareVM();
Init_heap();
Init_vm_objects();
Init_frozen_strings();
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
w/string.c
}
}
static int fstring_cmp(VALUE a, VALUE b);
/* in case we restart MVM development, this needs to be per-VM */
static st_table* frozen_strings;
static inline st_table*
rb_vm_fstring_table(void)
{
return frozen_strings;
}
static const struct st_hash_type fstring_hash_type = {
fstring_cmp,
rb_str_hash,
};
static int
fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
{
VALUE *fstr = (VALUE *)arg;
VALUE str = (VALUE)*key;
if (existing) {
/* because of lazy sweep, str may be unmarked already and swept
* at next time */
if (rb_objspace_garbage_object_p(str)) {
*fstr = Qundef;
return ST_DELETE;
}
*fstr = str;
return ST_STOP;
}
else {
if (STR_SHARED_P(str)) { /* str should not be shared */
str = rb_enc_str_new(RSTRING_PTR(str), RSTRING_LEN(str), STR_ENC_GET(str));
OBJ_FREEZE(str);
}
else {
str = rb_str_new_frozen(str);
}
RBASIC(str)->flags |= RSTRING_FSTR;
*key = *value = *fstr = str;
return ST_CONTINUE;
}
}
VALUE
rb_fstring(VALUE str)
{
VALUE ret;
Check_Type(str, T_STRING);
if (FL_TEST(str, RSTRING_FSTR))
return str;
do {
ret = str;
st_update(rb_vm_fstring_table(), (st_data_t)str,
fstr_update_callback, (st_data_t)&ret);
} while (ret == Qundef);
return ret;
}
static VALUE
setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx)
{
......
return setup_fake_str(fake_str, name, len, rb_enc_to_index(enc));
}
VALUE
rb_fstring_new(const char *ptr, long len)
{
struct RString fake_str;
return rb_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII));
}
static int
fstring_set_class_i(st_data_t key, st_data_t val, st_data_t arg)
{
RBASIC_SET_CLASS((VALUE)key, (VALUE)arg);
return ST_CONTINUE;
}
static int
fstring_cmp(VALUE a, VALUE b)
{
int cmp = rb_str_hash_cmp(a, b);
if (cmp != 0) {
return cmp;
}
return ENCODING_GET(b) - ENCODING_GET(a);
}
static inline int
single_byte_optimizable(VALUE str)
{
......
rb_str_free(VALUE str)
{
if (FL_TEST(str, RSTRING_FSTR)) {
st_data_t fstr = (st_data_t)str;
st_delete(rb_vm_fstring_table(), &fstr, NULL);
void rb_fstring_remove(VALUE str);
rb_fstring_remove(str);
}
if (!STR_EMBED_P(str) && !FL_TEST(str, STR_SHARED)) {
......
rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
assert(rb_vm_fstring_table());
st_foreach(rb_vm_fstring_table(), fstring_set_class_i, rb_cString);
}
void
Init_frozen_strings(void)
{
assert(!frozen_strings);
frozen_strings = st_init_table(&fstring_hash_type);
Init_frozen_strings();
}
w/vm.c
ruby_thread_init_stack(th);
}
static inline st_table *
rb_vm_fstring_table(void)
{
return GET_VM()->frozen_strings;
}
static int
fstring_cmp(VALUE a, VALUE b)
{
int cmp = rb_str_hash_cmp(a, b);
if (cmp != 0) {
return cmp;
}
return ENCODING_GET(b) - ENCODING_GET(a);
}
static const struct st_hash_type fstring_hash_type = {
fstring_cmp,
rb_str_hash,
};
static int
fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
{
VALUE *fstr = (VALUE *)arg;
VALUE str = (VALUE)*key;
if (existing) {
/* because of lazy sweep, str may be unmarked already and swept
* at next time */
if (rb_objspace_garbage_object_p(str)) {
*fstr = Qundef;
return ST_DELETE;
}
*fstr = str;
return ST_STOP;
}
else {
if (STR_SHARED_P(str)) { /* str should not be shared */
str = rb_enc_str_new(RSTRING_PTR(str), RSTRING_LEN(str), rb_enc_get(str));
OBJ_FREEZE(str);
}
else {
str = rb_str_new_frozen(str);
}
RBASIC(str)->flags |= RSTRING_FSTR;
*key = *value = *fstr = str;
return ST_CONTINUE;
}
}
VALUE
rb_fstring(VALUE str)
{
VALUE ret;
st_table *frozen_strings = rb_vm_fstring_table();
Check_Type(str, T_STRING);
if (FL_TEST(str, RSTRING_FSTR))
return str;
do {
ret = str;
st_update(frozen_strings, (st_data_t)str, fstr_update_callback, (st_data_t)&ret);
} while (ret == Qundef);
return ret;
}
VALUE
rb_fstring_new(const char *ptr, long len)
{
struct RString fake_str;
return rb_fstring(rb_setup_fake_str(&fake_str, ptr, len, rb_usascii_encoding()));
}
void
rb_fstring_remove(VALUE str)
{
st_data_t fstr = (st_data_t)str;
st_delete(rb_vm_fstring_table(), &fstr, NULL);
}
static int
fstring_set_class_i(st_data_t key, st_data_t val, st_data_t arg)
{
RBASIC_SET_CLASS((VALUE)key, (VALUE)arg);
return ST_CONTINUE;
}
void
Init_frozen_strings(void)
{
st_table *frozen_strings = rb_vm_fstring_table();
assert(frozen_strings);
st_foreach(frozen_strings, fstring_set_class_i, rb_cString);
}
void
Init_vm_objects(void)
{
......
/* initialize mark object array, hash */
vm->mark_object_ary = rb_ary_tmp_new(128);
assert(!vm->frozen_strings);
vm->frozen_strings = st_init_table(&fstring_hash_type);
}
/* top self */
(2-2/2)