ruby-changes:7557
From: nobu <ko1@a...>
Date: Wed, 3 Sep 2008 16:53:32 +0900 (JST)
Subject: [ruby-changes:7557] Ruby:r19078 (ruby_1_8): * gc.c (rb_mark_set): new function to mark keys.
nobu 2008-09-03 16:53:19 +0900 (Wed, 03 Sep 2008) New Revision: 19078 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=19078 Log: * gc.c (rb_mark_set): new function to mark keys. * marshal.c (struct dump_arg, struct load_arg): added wrappers to mark data entries. backport from trunk r13527,r13528,r13961,r16533. [ruby-dev:36082] Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/gc.c branches/ruby_1_8/intern.h branches/ruby_1_8/marshal.c branches/ruby_1_8/test/ruby/marshaltestlib.rb branches/ruby_1_8/test/ruby/test_marshal.rb Index: ruby_1_8/intern.h =================================================================== --- ruby_1_8/intern.h (revision 19077) +++ ruby_1_8/intern.h (revision 19078) @@ -257,6 +257,7 @@ char *rb_source_filename _((const char*)); void rb_gc_mark_locations _((VALUE*, VALUE*)); void rb_mark_tbl _((struct st_table*)); +void rb_mark_set _((struct st_table*)); void rb_mark_hash _((struct st_table*)); void rb_gc_mark_maybe _((VALUE)); void rb_gc_mark _((VALUE)); Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 19077) +++ ruby_1_8/ChangeLog (revision 19078) @@ -1,3 +1,11 @@ +Wed Sep 3 16:53:17 2008 Nobuyoshi Nakada <nobu@r...> + + * gc.c (rb_mark_set): new function to mark keys. + + * marshal.c (struct dump_arg, struct load_arg): added wrappers to mark + data entries. backport from trunk r13527,r13528,r13961,r16533. + [ruby-dev:36082] + Tue Sep 2 23:39:45 2008 Yusuke Endoh <mame@t...> * marshal.c (w_object): add a check for modification of array during Index: ruby_1_8/marshal.c =================================================================== --- ruby_1_8/marshal.c (revision 19077) +++ ruby_1_8/marshal.c (revision 19078) @@ -84,22 +84,13 @@ static ID s_dump_data, s_load_data, s_alloc, s_call; static ID s_getc, s_read, s_write, s_binmode; -static void -reentrant_check(obj, sym) - VALUE obj; - ID sym; -{ - if (obj && RBASIC(obj)->klass) { - rb_raise(rb_eRuntimeError, "%s reentered", rb_id2name(sym)); - } -} - struct dump_arg { VALUE obj; VALUE str, dest; st_table *symbols; st_table *data; int taint; + VALUE wrapper; }; struct dump_call_arg { @@ -108,6 +99,27 @@ int limit; }; +static void +check_dump_arg(arg, sym) + struct dump_arg *arg; + ID sym; +{ + if (!DATA_PTR(arg->wrapper)) { + rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s", + rb_id2name(sym)); + } +} + +static void +mark_dump_arg(ptr) + void *ptr; +{ + struct dump_arg *p = ptr; + if (!ptr) + return; + rb_mark_set(p->data); +} + static VALUE class2path(klass) VALUE klass; @@ -515,7 +527,7 @@ volatile VALUE v; v = rb_funcall(obj, s_mdump, 0, 0); - reentrant_check(arg->str, s_mdump); + check_dump_arg(arg, s_mdump); w_class(TYPE_USRMARSHAL, obj, arg, Qfalse); w_object(v, arg, limit); if (ivtbl) w_ivar(0, &c_arg); @@ -525,7 +537,7 @@ VALUE v; v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); - reentrant_check(arg->str, s_dump); + check_dump_arg(arg, s_dump); if (TYPE(v) != T_STRING) { rb_raise(rb_eTypeError, "_dump() must return string"); } @@ -671,7 +683,7 @@ rb_obj_classname(obj)); } v = rb_funcall(obj, s_dump_data, 0); - reentrant_check(arg->str, s_dump_data); + check_dump_arg(arg, s_dump_data); w_class(TYPE_DATA, obj, arg, Qtrue); w_object(v, arg, limit); } @@ -704,9 +716,11 @@ dump_ensure(arg) struct dump_arg *arg; { - if (RBASIC(arg->str)->klass) return 0; /* ignore reentrant */ + if (!DATA_PTR(arg->wrapper)) return 0; st_free_table(arg->symbols); st_free_table(arg->data); + DATA_PTR(arg->wrapper) = 0; + arg->wrapper = 0; if (arg->taint) { OBJ_TAINT(arg->str); } @@ -773,7 +787,7 @@ arg.dest = port; if (rb_respond_to(port, s_binmode)) { rb_funcall2(port, s_binmode, 0, 0); - reentrant_check(arg.str, s_dump_data); + check_dump_arg(&arg, s_dump_data); } } else { @@ -783,6 +797,7 @@ arg.symbols = st_init_numtable(); arg.data = st_init_numtable(); arg.taint = Qfalse; + arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg); c_arg.obj = obj; c_arg.arg = &arg; c_arg.limit = limit; @@ -800,11 +815,33 @@ VALUE src; long offset; st_table *symbols; - VALUE data; + st_table *data; VALUE proc; int taint; + VALUE wrapper; }; +static void +check_load_arg(arg, sym) + struct load_arg *arg; + ID sym; +{ + if (!DATA_PTR(arg->wrapper)) { + rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s", + rb_id2name(sym)); + } +} + +static void +mark_load_arg(ptr) + void *ptr; +{ + struct load_arg *p = ptr; + if (!ptr) + return; + rb_mark_tbl(p->data); +} + static VALUE r_object _((struct load_arg *arg)); static int @@ -824,7 +861,7 @@ else { VALUE src = arg->src; VALUE v = rb_funcall2(src, s_getc, 0, 0); - reentrant_check(arg->data, s_getc); + check_load_arg(arg, s_getc); if (NIL_P(v)) rb_eof_error(); c = (unsigned char)FIX2INT(v); } @@ -905,7 +942,7 @@ VALUE src = arg->src; VALUE n = LONG2NUM(len); str = rb_funcall2(src, s_read, 1, &n); - reentrant_check(arg->data, s_read); + check_load_arg(arg, s_read); if (NIL_P(str)) goto too_short; StringValue(str); if (RSTRING(str)->len != len) goto too_short; @@ -968,7 +1005,7 @@ VALUE v; struct load_arg *arg; { - rb_hash_aset(arg->data, INT2FIX(RHASH(arg->data)->tbl->num_entries), v); + st_insert(arg->data, arg->data->num_entries, (st_data_t)v); if (arg->taint) OBJ_TAINT(v); return v; } @@ -1024,14 +1061,15 @@ VALUE v = Qnil; int type = r_byte(arg); long id; + st_data_t link; switch (type) { case TYPE_LINK: id = r_long(arg); - v = rb_hash_aref(arg->data, LONG2FIX(id)); - if (NIL_P(v)) { + if (!st_lookup(arg->data, (st_data_t)id, &link)) { rb_raise(rb_eArgError, "dump format error (unlinked)"); } + v = (st_data_t)link; return v; case TYPE_IVAR: @@ -1256,7 +1294,7 @@ *ivp = Qfalse; } v = rb_funcall(klass, s_load, 1, data); - reentrant_check(arg->data, s_load); + check_load_arg(arg, s_load); r_entry(v, arg); } break; @@ -1280,7 +1318,7 @@ r_entry(v, arg); data = r_object(arg); rb_funcall(v, s_mload, 1, data); - reentrant_check(arg->data, s_mload); + check_load_arg(arg, s_mload); } break; @@ -1307,7 +1345,7 @@ warn = Qfalse; } v = rb_funcall(klass, s_alloc, 0); - reentrant_check(arg->data, s_alloc); + check_load_arg(arg, s_alloc); } else { v = rb_obj_alloc(klass); @@ -1322,7 +1360,7 @@ rb_class2name(klass)); } rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0, extmod)); - reentrant_check(arg->data, s_load_data); + check_load_arg(arg, s_load_data); } break; @@ -1366,7 +1404,7 @@ } if (proc) { rb_funcall(proc, s_call, 1, v); - reentrant_check(arg->data, s_call); + check_load_arg(arg, s_call); } return v; } @@ -1389,8 +1427,11 @@ load_ensure(arg) struct load_arg *arg; { - if (RBASIC(arg->data)->klass) return 0; /* ignore reentrant */ + if (!DATA_PTR(arg->wrapper)) return 0; st_free_table(arg->symbols); + st_free_table(arg->data); + DATA_PTR(arg->wrapper) = 0; + arg->wrapper = 0; return 0; } @@ -1432,7 +1473,10 @@ } arg.src = port; arg.offset = 0; - arg.data = 0; + arg.symbols = st_init_numtable(); + arg.data = st_init_numtable(); + arg.proc = 0; + arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg); major = r_byte(&arg); minor = r_byte(&arg); @@ -1447,11 +1491,7 @@ MARSHAL_MAJOR, MARSHAL_MINOR, major, minor); } - arg.symbols = st_init_numtable(); - arg.data = rb_hash_new(); - RBASIC(arg.data)->klass = 0; - if (NIL_P(proc)) arg.proc = 0; - else arg.proc = proc; + if (!NIL_P(proc)) arg.proc = proc; v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); RBASIC(arg.data)->klass = rb_cHash; Index: ruby_1_8/test/ruby/test_marshal.rb =================================================================== --- ruby_1_8/test/ruby/test_marshal.rb (revision 19077) +++ ruby_1_8/test/ruby/test_marshal.rb (revision 19078) @@ -12,11 +12,17 @@ include MarshalTestLib def encode(o) + stress, GC.stress = GC.stress, true Marshal.dump(o) + ensure + GC.stress = stress end def decode(s) + stress, GC.stress = GC.stress, true Marshal.load(s) + ensure + GC.stress = stress end def fact(n) Index: ruby_1_8/test/ruby/marshaltestlib.rb =================================================================== --- ruby_1_8/test/ruby/marshaltestlib.rb (revision 19077) +++ ruby_1_8/test/ruby/marshaltestlib.rb (revision 19078) @@ -193,6 +193,12 @@ 1.instance_eval { remove_instance_variable("@iv") } end + def test_fixnum_64bit + obj = [1220278665, 1220278662, 1220278661, 1220278661, 1220278656] + + marshal_equal(obj) + end + def test_float marshal_equal(-1.0) marshal_equal(0.0) Index: ruby_1_8/gc.c =================================================================== --- ruby_1_8/gc.c (revision 19077) +++ ruby_1_8/gc.c (revision 19078) @@ -734,6 +734,31 @@ } static int +mark_key(key, value, lev) + VALUE key, value; + int lev; +{ + gc_mark(key, lev); + return ST_CONTINUE; +} + +static void +mark_set(tbl, lev) + st_table *tbl; + int lev; +{ + if (!tbl) return; + st_foreach(tbl, mark_key, lev); +} + +void +rb_mark_set(tbl) + st_table *tbl; +{ + mark_set(tbl, 0); +} + +static int mark_keyvalue(key, value, lev) VALUE key; VALUE value; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/