From e52da919872f8cf71c90a27b470cef724204eece Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 12 Feb 2009 10:42:36 +0000 Subject: [PATCH] * compile.c (compile_array_, defined_expr, iseq_compile_each): hide and freeze internal literal objects, to prevent from modifying. [ruby-dev:37959] * iseq.c (insn_operand_intern): copy internal literal objects. * insns.def (putstring, duparray): ditto. * string.c (rb_str_replace): exported. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22255 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 ++++++++++++ compile.c | 5 ++++- include/ruby/intern.h | 1 + insns.def | 4 ++-- iseq.c | 12 ++++++++++++ string.c | 18 ++++++++++-------- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9e0005fbd..2cfd0fc7f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Thu Feb 12 19:42:33 2009 Nobuyoshi Nakada + + * compile.c (compile_array_, defined_expr, iseq_compile_each): hide + and freeze internal literal objects, to prevent from modifying. + [ruby-dev:37959] + + * iseq.c (insn_operand_intern): copy internal literal objects. + + * insns.def (putstring, duparray): ditto. + + * string.c (rb_str_replace): exported. + Thu Feb 12 17:17:51 2009 Nobuyoshi Nakada * ext/stringio/stringio.c (strio_ungetc): calculates new position diff --git a/compile.c b/compile.c index 3e1d7fb92d..05572233ad 100644 --- a/compile.c +++ b/compile.c @@ -295,6 +295,7 @@ PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2); #define INIT_ANCHOR(name) \ (name##_body__.last = &name##_body__.anchor, name = &name##_body__) +#define hide_obj(obj) (void)(OBJ_FREEZE(obj), RBASIC(obj)->klass = 0) #include "optinsn.inc" #if OPT_INSTRUCTIONS_UNIFICATION @@ -2230,7 +2231,7 @@ compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, if (opt_p == Qtrue) { if (!poped) { - VALUE ary = rb_ary_new(); + VALUE ary = rb_ary_tmp_new(len); node = node_root; while (node) { rb_ary_push(ary, node->nd_head->nd_lit); @@ -2709,6 +2710,7 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, if (estr != 0) { if (needstr != Qfalse) { VALUE str = rb_str_new2(estr); + hide_obj(str); ADD_INSN1(ret, nd_line(node), putstring, str); iseq_add_mark_object_compile_time(iseq, str); } @@ -4353,6 +4355,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) case NODE_STR:{ debugp_param("nd_lit", node->nd_lit); if (!poped) { + hide_obj(node->nd_lit); ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit); } break; diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 100b6c0975..e268428579 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -617,6 +617,7 @@ int rb_str_cmp(VALUE, VALUE); VALUE rb_str_equal(VALUE str1, VALUE str2); VALUE rb_str_drop_bytes(VALUE, long); void rb_str_update(VALUE, long, long, VALUE); +VALUE rb_str_replace(VALUE, VALUE); VALUE rb_str_inspect(VALUE); VALUE rb_str_dump(VALUE); VALUE rb_str_split(VALUE, const char*); diff --git a/insns.def b/insns.def index cd779d1393..4eef8f64fa 100644 --- a/insns.def +++ b/insns.def @@ -373,7 +373,7 @@ putstring () (VALUE val) { - val = rb_str_new3(str); + val = rb_str_replace(rb_str_new(0, 0), str); } /** @@ -460,7 +460,7 @@ duparray () (VALUE val) { - val = rb_ary_dup(ary); + val = rb_ary_replace(rb_ary_new2(0), ary); } /** diff --git a/iseq.c b/iseq.c index 967b142425..de0bae7234 100644 --- a/iseq.c +++ b/iseq.c @@ -21,6 +21,8 @@ VALUE rb_cISeq; +#define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass) + static void compile_data_free(struct iseq_compile_data *compile_data) { @@ -699,6 +701,16 @@ insn_operand_intern(rb_iseq_t *iseq, op = ID2SYM(op); case TS_VALUE: /* VALUE */ + if (hidden_obj_p(op)) { + switch (BUILTIN_TYPE(op)) { + case T_STRING: + op = rb_str_replace(rb_str_new(0, 0), op); + break; + case T_ARRAY: + op = rb_ary_replace(rb_ary_new2(0), op); + break; + } + } ret = rb_inspect(op); if (CLASS_OF(op) == rb_cISeq) { rb_ary_push(child, op); diff --git a/string.c b/string.c index 802e9379bf..8eb83efcec 100644 --- a/string.c +++ b/string.c @@ -815,14 +815,18 @@ rb_obj_as_string(VALUE obj) return str; } -static VALUE rb_str_replace(VALUE, VALUE); +static VALUE +str_duplicate(VALUE klass, VALUE str) +{ + VALUE dup = str_alloc(klass); + rb_str_replace(dup, str); + return dup; +} VALUE rb_str_dup(VALUE str) { - VALUE dup = str_alloc(rb_obj_class(str)); - rb_str_replace(dup, str); - return dup; + return str_duplicate(rb_obj_class(str), str); } @@ -3722,7 +3726,7 @@ rb_str_gsub(int argc, VALUE *argv, VALUE str) * s.replace "world" #=> "world" */ -static VALUE +VALUE rb_str_replace(VALUE str, VALUE str2) { long len; @@ -4024,9 +4028,7 @@ static VALUE rb_str_to_s(VALUE str) { if (rb_obj_class(str) != rb_cString) { - VALUE dup = str_alloc(rb_cString); - rb_str_replace(dup, str); - return dup; + return str_duplicate(rb_cString, str); } return str; }