summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hash.c23
-rw-r--r--internal.h3
-rw-r--r--st.c20
-rw-r--r--string.c120
-rw-r--r--test/ruby/test_optimization.rb38
-rw-r--r--test/ruby/test_string.rb6
-rw-r--r--vm.c12
-rw-r--r--vm_core.h1
8 files changed, 32 insertions, 191 deletions
diff --git a/hash.c b/hash.c
index 6ae13ba..c47f21e 100644
--- a/hash.c
+++ b/hash.c
@@ -18,6 +18,7 @@
#include "probes.h"
#include "id.h"
#include "symbol.h"
+#include "gc.h"
#ifdef __APPLE__
# ifdef HAVE_CRT_EXTERNS_H
@@ -1515,13 +1516,33 @@ hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
return ST_CONTINUE;
}
+static VALUE
+fstring_existing_str(VALUE str)
+{
+ st_data_t fstr;
+ st_table *tbl = rb_vm_fstring_table();
+
+ if (st_lookup(tbl, str, &fstr)) {
+ if (rb_objspace_garbage_object_p(fstr)) {
+ return rb_fstring(str);
+ }
+ else {
+ return (VALUE)fstr;
+ }
+ }
+ else {
+ return Qnil;
+ }
+}
+
static int
hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
{
if (!existing && !RB_OBJ_FROZEN(*key)) {
VALUE k;
- if ((k = rb_fstring_existing(*key)) != Qnil) {
+ if (!RB_OBJ_TAINTED(*key) &&
+ (k = fstring_existing_str(*key)) != Qnil) {
*key = k;
}
else {
diff --git a/internal.h b/internal.h
index cddbb6b..2e66a64 100644
--- a/internal.h
+++ b/internal.h
@@ -1590,7 +1590,6 @@ VALUE rb_strftime(const char *format, size_t format_len, rb_encoding *enc,
/* string.c */
VALUE rb_fstring(VALUE);
VALUE rb_fstring_new(const char *ptr, long len);
-VALUE rb_fstring_existing(VALUE);
#define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str))
#define rb_fstring_literal(str) rb_fstring_lit(str)
VALUE rb_fstring_cstr(const char *str);
@@ -1743,7 +1742,7 @@ void rb_vm_check_redefinition_by_prepend(VALUE klass);
VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
VALUE ruby_vm_special_exception_copy(VALUE);
PUREFUNC(st_table *rb_vm_fstring_table(void));
-PUREFUNC(st_table *rb_vm_tfstring_table(void));
+
/* vm_dump.c */
void rb_print_backtrace(void);
diff --git a/st.c b/st.c
index c983c02..c2848b6 100644
--- a/st.c
+++ b/st.c
@@ -2092,23 +2092,6 @@ st_rehash(st_table *tab)
}
#ifdef RUBY
-
-static VALUE
-str_key(VALUE key)
-{
- VALUE k;
-
- if (RB_OBJ_FROZEN(key)) {
- return key;
- }
- if ((k = rb_fstring_existing(key)) != Qnil) {
- return k;
- }
- else {
- return rb_str_new_frozen(key);
- }
-}
-
/* Mimics ruby's { foo => bar } syntax. This function is placed here
because it touches table internals and write barriers at once. */
void
@@ -2131,7 +2114,8 @@ rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
for (i = 0; i < argc; /* */) {
VALUE key = argv[i++];
VALUE val = argv[i++];
- st_data_t k = (rb_obj_class(key) == rb_cString) ? str_key(key) : key;
+ st_data_t k = (rb_obj_class(key) == rb_cString) ?
+ rb_str_new_frozen(key) : key;
st_table_entry e;
e.hash = do_hash(k, tab);
e.key = k;
diff --git a/string.c b/string.c
index 932ed5e..2012a28 100644
--- a/string.c
+++ b/string.c
@@ -301,79 +301,27 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi
}
}
-static int
-tainted_fstr_update(st_data_t *key, st_data_t *val, 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 {
- str = rb_str_resurrect(str);
- RB_OBJ_TAINT_RAW(str);
- RB_FL_SET_RAW(str, RSTRING_FSTR);
- RB_OBJ_FREEZE_RAW(str);
-
- *key = *val = *fstr = str;
- return ST_CONTINUE;
- }
-}
-
-static VALUE
-register_fstring_tainted(VALUE str, st_table *tfstrings)
-{
- st_data_t fstr;
-
- do {
- fstr = (st_data_t)str;
- st_update(tfstrings, fstr, tainted_fstr_update, (st_data_t)&fstr);
- } while ((VALUE)fstr == Qundef);
-
- str = (VALUE)fstr;
- assert(OBJ_FROZEN_RAW(str));
- assert(!FL_TEST_RAW(str, STR_FAKESTR));
- assert(!FL_TEST_RAW(str, FL_EXIVAR));
- assert(FL_TEST_RAW(str, RSTRING_FSTR));
- assert(FL_TEST_RAW(str, FL_TAINT));
- assert(RBASIC_CLASS(str) == rb_cString);
-
- return str;
-}
-
RUBY_FUNC_EXPORTED
VALUE
rb_fstring(VALUE str)
{
VALUE fstr;
- int bare_ish;
+ int bare;
Check_Type(str, T_STRING);
if (FL_TEST(str, RSTRING_FSTR))
return str;
- bare_ish = !FL_TEST_RAW(str, FL_EXIVAR) && RBASIC_CLASS(str) == rb_cString;
- if (STR_EMBED_P(str) && !bare_ish) {
+ bare = BARE_STRING_P(str);
+ if (STR_EMBED_P(str) && !bare) {
OBJ_FREEZE_RAW(str);
return str;
}
- if (!FL_TEST_RAW(str, FL_TAINT)) {
- fstr = register_fstring(str);
- }
- else {
- fstr = register_fstring_tainted(str, rb_vm_tfstring_table());
- }
- if (!bare_ish) {
+
+ fstr = register_fstring(str);
+
+ if (!bare) {
str_replace_shared_without_enc(str, fstr);
OBJ_FREEZE_RAW(str);
return str;
@@ -402,59 +350,6 @@ register_fstring(VALUE str)
}
static VALUE
-rb_fstring_existing0(VALUE str)
-{
- st_table *frozen_strings = rb_vm_fstring_table();
- st_data_t fstr;
-
- if (st_lookup(frozen_strings, str, &fstr)) {
- if (rb_objspace_garbage_object_p(fstr)) {
- return register_fstring(str);
- }
- else {
- return (VALUE)fstr;
- }
- }
- return Qnil;
-}
-
-static VALUE
-rb_tainted_fstring_existing(VALUE str)
-{
- VALUE ret;
- st_data_t fstr;
- st_table *tfstrings = rb_vm_tfstring_table();
-
- if (st_lookup(tfstrings, str, &fstr)) {
- ret = (VALUE)fstr;
- if (!rb_objspace_garbage_object_p(ret)) {
- return ret;
- }
- }
- ret = rb_fstring_existing0(str);
- if (NIL_P(ret)) {
- return Qnil;
- }
- if (!RB_FL_TEST_RAW(ret, RSTRING_FSTR)) {
- return Qnil;
- }
-
- return register_fstring_tainted(str, tfstrings);
-}
-
-VALUE
-rb_fstring_existing(VALUE str)
-{
- if (FL_TEST_RAW(str, RSTRING_FSTR))
- return str;
-
- if (!RB_OBJ_TAINTED_RAW(str))
- return rb_fstring_existing0(str);
-
- return rb_tainted_fstring_existing(str);
-}
-
-static VALUE
setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx)
{
fake_str->basic.flags = T_STRING|RSTRING_NOEMBED|STR_NOFREE|STR_FAKESTR;
@@ -1416,7 +1311,6 @@ 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);
- st_delete(rb_vm_tfstring_table(), &fstr, NULL);
RB_DEBUG_COUNTER_INC(obj_str_fstr);
}
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 6cf6c63..2d0eec0 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -181,44 +181,6 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('Hash', 'empty?', 'assert_nil({}.empty?); assert_nil({1=>1}.empty?)')
end
- def test_hash_reuse_fstring
- embed = -'h e l l o'
- shared = -'this string is too long to be embedded and should be shared'
- assert_not_equal GC::INTERNAL_CONSTANTS[:RVALUE_SIZE],
- ObjectSpace.memsize_of(shared),
- 'update this test if string embedding changed'
-
- [ embed, shared ].each do |exp|
- key = exp.split(' ').join(' ')
- h = {}
- h[key] = true
- assert_not_same key, h.keys[0]
- assert_predicate h.keys[0], :frozen?
- assert_same exp, h.keys[0]
-
- h = { key => 1 }
- assert_same exp, h.keys[0], 'newhash insn should reuse strings, too'
-
- h1 = {}
- h2 = {}
- key.taint
- h1[key] = true
- h2[key] = true
- k1 = h1.keys[0]
- k2 = h2.keys[0]
- assert_same k1, k2
- assert_predicate k1, :tainted?
-
- h = { key => 1 }
- assert_not_predicate key, :frozen?
- assert_same k1, h.keys[0], 'newhash insn should reuse tainted strings'
-
- assert_equal GC::INTERNAL_CONSTANTS[:RVALUE_SIZE],
- ObjectSpace.memsize_of(k1),
- 'tainted string should share with untainted fstring'
- end
- end
-
def test_hash_aref_with
h = { "foo" => 1 }
assert_equal 1, h["foo"]
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index e68a307..8696e16 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -2750,14 +2750,8 @@ CODE
assert_not_same(str, +str)
assert_same(str, -str)
- return unless @cls == String
bar = %w(b a r).join('')
- assert_not_predicate bar, :tainted?
- assert_not_predicate str, :tainted?
assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
- bar = %w(b a r).taint.join('')
- tstr = str.dup.taint
- assert_same -tstr, -bar
end
def test_ord
diff --git a/vm.c b/vm.c
index 75ca12f..814f8b6 100644
--- a/vm.c
+++ b/vm.c
@@ -2206,10 +2206,6 @@ ruby_vm_destruct(rb_vm_t *vm)
st_free_table(vm->frozen_strings);
vm->frozen_strings = 0;
}
- if (vm->tainted_frozen_strings) {
- st_free_table(vm->tainted_frozen_strings);
- vm->tainted_frozen_strings = 0;
- }
rb_vm_gvl_destroy(vm);
if (objspace) {
rb_objspace_free(objspace);
@@ -3146,8 +3142,6 @@ Init_vm_objects(void)
vm->mark_object_ary = rb_ary_tmp_new(128);
vm->loading_table = st_init_strtable();
vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 1000);
- vm->tainted_frozen_strings =
- st_init_table_with_size(&rb_fstring_hash_type, 1000);
}
/* top self */
@@ -3209,12 +3203,6 @@ rb_vm_fstring_table(void)
return GET_VM()->frozen_strings;
}
-st_table *
-rb_vm_tfstring_table(void)
-{
- return GET_VM()->tainted_frozen_strings;
-}
-
#if VM_COLLECT_USAGE_DETAILS
#define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v))
diff --git a/vm_core.h b/vm_core.h
index fce3cd4..c23f506 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -574,7 +574,6 @@ typedef struct rb_vm_struct {
VALUE *defined_strings;
st_table *frozen_strings;
- st_table *tainted_frozen_strings;
/* params */
struct { /* size in byte */