Feature #10182 » mvm-fstring.patch
| 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 */
|
||
- « Previous
- 1
- 2
- Next »