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 »