From 6fd900007616801f4c8adcc0228fe06bd6f1f873 Mon Sep 17 00:00:00 2001 From: charliesome Date: Thu, 5 Sep 2013 04:49:16 +0000 Subject: * include/ruby/ruby.h: add RSTRING_FSTR flag * internal.h: add rb_fstring() prototype * parse.y (str_suffix_gen): deduplicate frozen string literals * string.c (rb_fstring): deduplicate frozen string literals * string.c (rb_str_free): delete fstrings from frozen_strings table when they are GC'd * string.c (Init_String): initialize frozen_strings table * test/ruby/test_string.rb: test frozen strings are deduplicated git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42843 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- string.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'string.c') diff --git a/string.c b/string.c index 4bc26df81e..7ee4730930 100644 --- a/string.c +++ b/string.c @@ -131,6 +131,26 @@ VALUE rb_cSymbol; #define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str)) +static st_table* frozen_strings; + +static const struct st_hash_type fstring_hash_type = { + rb_str_cmp, + rb_str_hash +}; + +VALUE +rb_fstring(VALUE str) +{ + VALUE fstr; + if (!st_lookup(frozen_strings, (st_data_t)str, (st_data_t*)&fstr)) { + fstr = rb_str_dup(str); + OBJ_FREEZE(fstr); + RBASIC(fstr)->flags |= RSTRING_FSTR; + st_insert(frozen_strings, fstr, fstr); + } + return fstr; +} + static inline int single_byte_optimizable(VALUE str) { @@ -838,6 +858,9 @@ rb_free_tmp_buffer(volatile VALUE *store) void rb_str_free(VALUE str) { + if (FL_TEST(str, RSTRING_FSTR)) { + st_delete(frozen_strings, (st_data_t*)&str, NULL); + } if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) { xfree(RSTRING(str)->as.heap.ptr); } @@ -8672,6 +8695,8 @@ Init_String(void) #undef rb_intern #define rb_intern(str) rb_intern_const(str) + frozen_strings = st_init_table(&fstring_hash_type); + rb_cString = rb_define_class("String", rb_cObject); rb_include_module(rb_cString, rb_mComparable); rb_define_alloc_func(rb_cString, empty_str_alloc); -- cgit v1.2.3