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 »