[前][次][番号順一覧][スレッド一覧]

ruby-changes:1922

From: ko1@a...
Date: 9 Sep 2007 00:07:29 +0900
Subject: [ruby-changes:1922] akr - Ruby:r13413 (trunk): * eval_method.ci (rb_get_alloc_func): new function to get allocation

akr	2007-09-09 00:07:18 +0900 (Sun, 09 Sep 2007)

  New Revision: 13413

  Modified files:
    trunk/ChangeLog
    trunk/eval_method.ci
    trunk/include/ruby/intern.h
    trunk/inits.c
    trunk/marshal.c
    trunk/range.c

  Log:
    * eval_method.ci (rb_get_alloc_func): new function to get allocation
      function.
    
    * include/ruby/intern.h (rb_alloc_func_t): declared.
      (rb_define_alloc_func): declared.
      (rb_marshal_define_compat): declared.
    
    * range.c: use T_STRUCT for Range.
    
    * inits.c: move Init_marshal() prior to Init_Range() because
      Init_Range calls rb_marshal_define_compat which needs
      marshal's compat_allocator_tbl initialized.
    
    * marshal.c: support marshal format compatibility layer designed for
      marshaling T_STRUCT Range using T_OBJECT format.
      (rb_marshal_define_compat): defined.
    
    [ruby-dev:31710]


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=13413&r2=13412
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_method.ci?r1=13413&r2=13412
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/range.c?r1=13413&r2=13412
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/marshal.c?r1=13413&r2=13412
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/inits.c?r1=13413&r2=13412
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/include/ruby/intern.h?r1=13413&r2=13412

Index: eval_method.ci
===================================================================
--- eval_method.ci	(revision 13412)
+++ eval_method.ci	(revision 13413)
@@ -192,6 +192,19 @@
     rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
 }
 
+rb_alloc_func_t
+rb_get_alloc_func(VALUE klass)
+{
+    NODE *n;
+    Check_Type(klass, T_CLASS);
+    n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
+    if (!n) return 0;
+    if (nd_type(n) != NODE_METHOD) return 0;
+    n = n->nd_body;
+    if (nd_type(n) != NODE_CFUNC) return 0;
+    return n->nd_cfnc;
+}
+
 static NODE *
 search_method(VALUE klass, ID id, VALUE *klassp)
 {
Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 13412)
+++ include/ruby/intern.h	(revision 13413)
@@ -219,8 +219,10 @@
 #define rb_disable_super(klass, name) ((void)0)
 #define rb_enable_super(klass, name) ((void)0)
 #define HAVE_RB_DEFINE_ALLOC_FUNC 1
-void rb_define_alloc_func(VALUE, VALUE (*)(VALUE));
+typedef VALUE (*rb_alloc_func_t)(VALUE);
+void rb_define_alloc_func(VALUE, rb_alloc_func_t);
 void rb_undef_alloc_func(VALUE);
+rb_alloc_func_t rb_get_alloc_func(VALUE);
 void rb_clear_cache(void);
 void rb_clear_cache_by_class(VALUE);
 void rb_alias(VALUE, ID, ID);
@@ -356,6 +358,7 @@
 /* marshal.c */
 VALUE rb_marshal_dump(VALUE, VALUE);
 VALUE rb_marshal_load(VALUE);
+void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE));
 /* numeric.c */
 void rb_num_zerodiv(void);
 VALUE rb_num_coerce_bin(VALUE, VALUE);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 13412)
+++ ChangeLog	(revision 13413)
@@ -1,3 +1,24 @@
+Sat Sep  8 23:55:56 2007  Tanaka Akira  <akr@f...>
+
+	* eval_method.ci (rb_get_alloc_func): new function to get allocation
+	  function.
+
+	* include/ruby/intern.h (rb_alloc_func_t): declared.
+	  (rb_define_alloc_func): declared.
+	  (rb_marshal_define_compat): declared.
+
+	* range.c: use T_STRUCT for Range.
+
+	* inits.c: move Init_marshal() prior to Init_Range() because
+	  Init_Range calls rb_marshal_define_compat which needs
+	  marshal's compat_allocator_tbl initialized.
+
+	* marshal.c: support marshal format compatibility layer designed for
+	  marshaling T_STRUCT Range using T_OBJECT format.
+	  (rb_marshal_define_compat): defined.
+	
+	[ruby-dev:31710]
+
 Sat Sep  8 10:05:14 2007  Yukihiro Matsumoto  <matz@r...>
 
 	* struct.c (rb_struct_s_members): check if __members__ is an
@@ -129,6 +150,8 @@
 
 	* .gdbinit: support embedded small bignums.
 
+	[ruby-dev:31689]
+
 Sat Sep  1 19:59:43 2007  Masaki Suketa  <masaki.suketa@n...>
 
 	* ext/win32ole/win32ole.c (ole_event_free): IConnectionPoint should be
@@ -241,9 +264,11 @@
 
 	* ext/tk/tkutil/tkutil.c: ditto.
 
+	[ruby-dev:31678]
+
 Wed Aug 29 18:36:06 2007  Tanaka Akira  <akr@f...>
 
-	* lib/open-uri.rb: add :ftp_active_mode option.
+	* lib/open-uri.rb: add :ftp_active_mode option.  [ruby-dev:31677]
 
 Wed Aug 29 14:55:28 2007  Yukihiro Matsumoto  <matz@r...>
 
@@ -271,6 +296,8 @@
 	  (st_foreach): ditto.
 	  (st_reverse_foreach): ditto.
 	  (unpack_entries): new function for converting to unpacked mode.
+
+	[ruby-list:43954]
 	  
 Wed Aug 29 10:46:37 2007  Yukihiro Matsumoto  <matz@r...>
 
@@ -761,6 +788,7 @@
 Tue Aug 21 21:09:48 2007  Tanaka Akira  <akr@f...>
 
 	* lib/tmpdir.rb (Dir.mktmpdir): make directory suffix specifiable.
+	  suggested by knu.  [ruby-dev:31568]
 
 Tue Aug 21 15:00:23 2007  Koichi Sasada  <ko1@a...>
 
Index: range.c
===================================================================
--- range.c	(revision 13412)
+++ range.c	(revision 13413)
@@ -15,10 +15,34 @@
 VALUE rb_cRange;
 static ID id_cmp, id_succ, id_beg, id_end, id_excl;
 
-#define EXCL(r) RTEST(rb_ivar_get((r), id_excl))
-#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse)
+#define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
+#define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
+#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
 
+#define EXCL(r) RTEST(RANGE_EXCL(r))
+#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
+
+#define FL_INITIALIZED FL_USER3
+
 static VALUE
+range_alloc(VALUE klass)
+{
+    long n;
+    NEWOBJ(r, struct RStruct);
+    OBJSETUP(r, klass, T_STRUCT);
+
+    n = 3;
+
+    RBASIC(r)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
+    RBASIC(r)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
+    rb_mem_clear(r->as.ary, n);
+
+    RBASIC(r)->flags &= ~FL_INITIALIZED;
+
+    return (VALUE)r;
+}
+
+static VALUE
 range_failed(void)
 {
     rb_raise(rb_eArgError, "bad value for range");
@@ -48,8 +72,8 @@
     }
 
     SET_EXCL(range, exclude_end);
-    rb_ivar_set(range, id_beg, beg);
-    rb_ivar_set(range, id_end, end);
+    RSTRUCT(range)->as.ary[0] = beg;
+    RSTRUCT(range)->as.ary[1] = end;
 }
 
 VALUE
@@ -77,9 +101,10 @@
     
     rb_scan_args(argc, argv, "21", &beg, &end, &flags);
     /* Ranges are immutable, so that they should be initialized only once. */
-    if (rb_ivar_defined(range, id_beg)) {
+    if (RBASIC(range)->flags & FL_INITIALIZED) {
 	rb_name_error(rb_intern("initialize"), "`initialize' called twice");
     }
+    RBASIC(range)->flags |= FL_INITIALIZED;
     range_init(range, beg, end, RTEST(flags));
     return Qnil;
 }
@@ -121,9 +146,9 @@
     if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
 	return Qfalse;
 
-    if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
+    if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
 	return Qfalse;
-    if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
+    if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
 	return Qfalse;
 
     if (EXCL(range) != EXCL(obj))
@@ -183,9 +208,9 @@
     if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
 	return Qfalse;
 
-    if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
+    if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
 	return Qfalse;
-    if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
+    if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
 	return Qfalse;
 
     if (EXCL(range) != EXCL(obj))
@@ -209,9 +234,9 @@
     long hash = EXCL(range);
     VALUE v;
 
-    v = rb_hash(rb_ivar_get(range, id_beg));
+    v = rb_hash(RANGE_BEG(range));
     hash ^= v << 1;
-    v = rb_hash(rb_ivar_get(range, id_end));
+    v = rb_hash(RANGE_END(range));
     hash ^= v << 9;
     hash ^= EXCL(range) << 24;
 
@@ -289,8 +314,8 @@
 
     RETURN_ENUMERATOR(range, argc, argv);
 
-    b = rb_ivar_get(range, id_beg);
-    e = rb_ivar_get(range, id_end);
+    b = RANGE_BEG(range);
+    e = RANGE_END(range);
     if (rb_scan_args(argc, argv, "01", &step) == 0) {
 	step = INT2FIX(1);
     }
@@ -382,8 +407,8 @@
 
     RETURN_ENUMERATOR(range, 0, 0);
 
-    beg = rb_ivar_get(range, id_beg);
-    end = rb_ivar_get(range, id_end);
+    beg = RANGE_BEG(range);
+    end = RANGE_END(range);
 
     if (!rb_respond_to(beg, id_succ)) {
 	rb_raise(rb_eTypeError, "can't iterate from %s",
@@ -423,7 +448,7 @@
 static VALUE
 range_first(VALUE range)
 {
-    return rb_ivar_get(range, id_beg);
+    return RANGE_BEG(range);
 }
 
 
@@ -442,7 +467,7 @@
 static VALUE
 range_last(VALUE range)
 {
-    return rb_ivar_get(range, id_end);
+    return RANGE_END(range);
 }
 
 /*
@@ -464,8 +489,8 @@
 	return rb_call_super(0, 0);
     }
     else {
-	VALUE b = rb_ivar_get(range, id_beg);
-	VALUE e = rb_ivar_get(range, id_end);
+	VALUE b = RANGE_BEG(range);
+	VALUE e = RANGE_END(range);
 	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
 
 	if (c > 0 || (c == 0 && EXCL(range)))
@@ -489,14 +514,14 @@
 static VALUE
 range_max(VALUE range)
 {
-    VALUE e = rb_ivar_get(range, id_end);
+    VALUE e = RANGE_END(range);
     int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger);
 
     if (rb_block_given_p() || (EXCL(range) && !ip)) {
 	return rb_call_super(0, 0);
     }
     else {
-	VALUE b = rb_ivar_get(range, id_beg);
+	VALUE b = RANGE_BEG(range);
 	int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
 
 	if (c > 0)
@@ -519,8 +544,8 @@
     long beg, end, excl;
 
     if (rb_obj_is_kind_of(range, rb_cRange)) {
-	b = rb_ivar_get(range, id_beg);
-	e = rb_ivar_get(range, id_end);
+	b = RANGE_BEG(range);
+	e = RANGE_END(range);
 	excl = EXCL(range);
     }
     else {
@@ -578,8 +603,8 @@
 {
     VALUE str, str2;
 
-    str = rb_obj_as_string(rb_ivar_get(range, id_beg));
-    str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
+    str = rb_obj_as_string(RANGE_BEG(range));
+    str2 = rb_obj_as_string(RANGE_END(range));
     str = rb_str_dup(str);
     rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
     rb_str_append(str, str2);
@@ -616,8 +641,8 @@
 {
     VALUE str, str2;
 
-    str = rb_inspect(rb_ivar_get(range, id_beg));
-    str2 = rb_inspect(rb_ivar_get(range, id_end));
+    str = rb_inspect(RANGE_BEG(range));
+    str2 = rb_inspect(RANGE_END(range));
     str = rb_str_dup(str);
     rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
     rb_str_append(str, str2);
@@ -668,8 +693,8 @@
 static VALUE
 range_include(VALUE range, VALUE val)
 {
-    VALUE beg = rb_ivar_get(range, id_beg);
-    VALUE end = rb_ivar_get(range, id_end);
+    VALUE beg = RANGE_BEG(range);
+    VALUE end = RANGE_END(range);
     int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
 	     rb_obj_is_kind_of(beg, rb_cNumeric) ||
 	     rb_obj_is_kind_of(end, rb_cNumeric);
@@ -711,8 +736,8 @@
 {
     VALUE beg, end;
 
-    beg = rb_ivar_get(range, id_beg);
-    end = rb_ivar_get(range, id_end);
+    beg = RANGE_BEG(range);
+    end = RANGE_END(range);
     if (r_le(beg, val)) {
 	if (EXCL(range)) {
 	    if (r_lt(val, end))
@@ -726,7 +751,34 @@
     return Qfalse;
 }
 
+static VALUE
+range_dumper(VALUE range)
+{
+    VALUE v;
+    NEWOBJ(m, struct RObject);
+    OBJSETUP(m, rb_cObject, T_OBJECT);
 
+    v = (VALUE)m;
+
+    rb_ivar_set(v, id_excl, EXCL(range) ? Qtrue : Qfalse);
+    rb_ivar_set(v, id_beg, RANGE_BEG(range));
+    rb_ivar_set(v, id_end, RANGE_END(range));
+    return v;
+}
+
+static VALUE
+range_loader(VALUE range, VALUE obj)
+{
+    if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
+        rb_raise(rb_eTypeError, "not a dumped range object");
+    }
+
+    RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
+    RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
+    SET_EXCL(range, RTEST(rb_ivar_get(obj, id_excl)));
+    return range;
+}
+
 /*  A <code>Range</code> represents an interval---a set of values with a
  *  start and an end. Ranges may be constructed using the
  *  <em>s</em><code>..</code><em>e</em> and
@@ -782,8 +834,25 @@
 void
 Init_Range(void)
 {
+    VALUE members;
+
+    id_cmp = rb_intern("<=>");
+    id_succ = rb_intern("succ");
+    id_beg = rb_intern("begin");
+    id_end = rb_intern("end");
+    id_excl = rb_intern("excl");
+
     rb_cRange = rb_define_class("Range", rb_cObject);
+
+    /* compatibility for rb_struct_members, etc. */
+    members = rb_ary_new3(3, ID2SYM(id_beg), ID2SYM(id_end), ID2SYM(id_excl));
+    OBJ_FREEZE(members);
+    rb_iv_set(rb_cRange, "__size__", INT2FIX(3));
+    rb_iv_set(rb_cRange, "__members__", members);
+
+    rb_define_alloc_func(rb_cRange, range_alloc);
     rb_include_module(rb_cRange, rb_mEnumerable);
+    rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader);
     rb_define_method(rb_cRange, "initialize", range_initialize, -1);
     rb_define_method(rb_cRange, "==", range_eq, 1);
     rb_define_method(rb_cRange, "===", range_eqq, 1);
@@ -807,9 +876,4 @@
     rb_define_method(rb_cRange, "include?", range_include, 1);
     rb_define_method(rb_cRange, "cover?", range_cover, 1);
 
-    id_cmp = rb_intern("<=>");
-    id_succ = rb_intern("succ");
-    id_beg = rb_intern("begin");
-    id_end = rb_intern("end");
-    id_excl = rb_intern("excl");
 }
Index: inits.c
===================================================================
--- inits.c	(revision 13412)
+++ inits.c	(revision 13413)
@@ -76,6 +76,7 @@
     Init_Struct();
     Init_Regexp();
     Init_pack();
+    Init_marshal();
     Init_Range();
     Init_IO();
     Init_Dir();
@@ -88,7 +89,6 @@
     Init_Binding();
     Init_Math();
     Init_GC();
-    Init_marshal();
     Init_Enumerator();
     Init_VM();
     Init_ISeq();
Index: marshal.c
===================================================================
--- marshal.c	(revision 13412)
+++ marshal.c	(revision 13413)
@@ -82,12 +82,45 @@
 static ID s_dump_data, s_load_data, s_alloc;
 static ID s_getc, s_read, s_write, s_binmode;
 
+typedef struct {
+    VALUE newclass;
+    VALUE oldclass;
+    VALUE (*dumper)(VALUE);
+    VALUE (*loader)(VALUE, VALUE);
+} marshal_compat_t;
+
+static st_table *compat_allocator_tbl;
+
+void
+rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE))
+{
+    marshal_compat_t *compat;
+    rb_alloc_func_t allocator = rb_get_alloc_func(newclass);
+
+    if (!allocator) {
+        rb_raise(rb_eTypeError, "no allocator");
+    }
+
+    compat = ALLOC(marshal_compat_t);
+    compat->newclass = Qnil;
+    compat->oldclass = Qnil;
+    rb_gc_register_address(&compat->newclass);
+    rb_gc_register_address(&compat->oldclass);
+    compat->newclass = newclass;
+    compat->oldclass = oldclass;
+    compat->dumper = dumper;
+    compat->loader = loader;
+
+    st_insert(compat_allocator_tbl, (st_data_t)allocator, (st_data_t)compat);
+}
+
 struct dump_arg {
     VALUE obj;
     VALUE str, dest;
     st_table *symbols;
     st_table *data;
     int taint;
+    st_table *compat_tbl;
 };
 
 struct dump_call_arg {
@@ -363,8 +396,13 @@
 {
     volatile VALUE p;
     char *path;
+    VALUE real_obj;
+    VALUE klass;
 
-    VALUE klass = CLASS_OF(obj);
+    if (st_lookup(arg->compat_tbl, (st_data_t)obj, (st_data_t*)&real_obj)) {
+        obj = real_obj;
+    }
+    klass = CLASS_OF(obj);
     w_extended(klass, arg, check);
     w_byte(type, arg);
     p = class2path(rb_class_real(klass));
@@ -459,6 +497,19 @@
 	if (OBJ_TAINTED(obj)) arg->taint = Qtrue;
 
 	st_add_direct(arg->data, obj, arg->data->num_entries);
+
+        {
+            marshal_compat_t *compat;
+            rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
+            if (st_lookup(compat_allocator_tbl,
+                          (st_data_t)allocator,
+                          (st_data_t*)&compat)) {
+                VALUE real_obj = obj;
+                obj = compat->dumper(real_obj);
+                st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
+            }
+        }
+
 	if (rb_respond_to(obj, s_mdump)) {
 	    VALUE v;
 
@@ -720,6 +771,7 @@
     arg.symbols = st_init_numtable();
     arg.data    = st_init_numtable();
     arg.taint   = Qfalse;
+    arg.compat_tbl = st_init_numtable();
     c_arg.obj   = obj;
     c_arg.arg   = &arg;
     c_arg.limit = limit;
@@ -739,6 +791,7 @@
     VALUE data;
     VALUE proc;
     int taint;
+    st_table *compat_tbl;
 };
 
 static VALUE r_entry(VALUE v, struct load_arg *arg);
@@ -899,14 +952,41 @@
 static VALUE
 r_entry(VALUE v, struct load_arg *arg)
 {
-    rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
-    if (arg->taint) OBJ_TAINT(v);
+    VALUE real_obj = Qundef;
+    if (st_lookup(arg->compat_tbl, v, (st_data_t*)&real_obj)) {
+        rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), real_obj);
+    }
+    else {
+        rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
+    }
+    if (arg->taint) {
+        OBJ_TAINT(v);
+        if (real_obj != Qundef)
+            OBJ_TAINT(real_obj);
+    }
     if (arg->proc) {
 	v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
     }
     return v;
 }
 
+static VALUE
+r_leave(VALUE v, struct load_arg *arg)
+{
+    VALUE real_obj;
+    marshal_compat_t *compat;
+    if (st_lookup(arg->compat_tbl, v, &real_obj)) {
+        rb_alloc_func_t allocator = rb_get_alloc_func(CLASS_OF(real_obj));
+        st_data_t key = v;
+        if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, (st_data_t*)&compat)) {
+            compat->loader(real_obj, v);
+        }
+        st_delete(arg->compat_tbl, &key, 0);
+        return real_obj;
+    }
+    return v;
+}
+
 static void
 r_ivar(VALUE obj, struct load_arg *arg)
 {
@@ -945,6 +1025,26 @@
 }
 
 static VALUE
+obj_alloc_by_path(const char *path, struct load_arg *arg)
+{
+    VALUE klass;
+    marshal_compat_t *compat;
+    rb_alloc_func_t allocator;
+
+    klass = path2class(path);
+
+    allocator = rb_get_alloc_func(klass);
+    if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, (st_data_t*)&compat)) {
+        VALUE real_obj = rb_obj_alloc(klass);
+        VALUE obj = rb_obj_alloc(compat->oldclass);
+        st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
+        return obj;
+    }
+
+    return rb_obj_alloc(klass);
+}
+
+static VALUE
 r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
 {
     VALUE v = Qnil;
@@ -1049,6 +1149,7 @@
 	    }
 	    v = rb_float_new(d);
 	    v = r_entry(v, arg);
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1094,11 +1195,13 @@
 	    }
 	    v = rb_big_norm((VALUE)big);
 	    v = r_entry(v, arg);
+            v = r_leave(v, arg);
 	}
 	break;
 
       case TYPE_STRING:
 	v = r_entry(r_string(arg), arg);
+        v = r_leave(v, arg);
 	break;
 
       case TYPE_REGEXP:
@@ -1106,6 +1209,7 @@
 	    volatile VALUE str = r_bytes(arg);
 	    int options = r_byte(arg);
 	    v = r_entry(rb_reg_new(str, options), arg);
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1118,6 +1222,7 @@
 	    while (len--) {
 		rb_ary_push(v, r_object(arg));
 	    }
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1136,12 +1241,14 @@
 	    if (type == TYPE_HASH_DEF) {
 		RHASH(v)->ifnone = r_object(arg);
 	    }
+            v = r_leave(v, arg);
 	}
 	break;
 
       case TYPE_STRUCT:
 	{
-	    VALUE klass, mem, values;
+	    VALUE klass, mem;
+            volatile VALUE values;
 	    volatile long i;	/* gcc 2.7.2.3 -O2 bug?? */
 	    long len;
 	    ID slot;
@@ -1150,13 +1257,15 @@
 	    mem = rb_struct_s_members(klass);
 	    len = r_long(arg);
 
+            if (RARRAY_LEN(mem) != len) {
+                rb_raise(rb_eTypeError, "struct %s not compatible (struct size differs)",
+                         rb_class2name(klass));
+            }
+
+            v = rb_obj_alloc(klass);
+	    v = r_entry(v, arg);
 	    values = rb_ary_new2(len);
 	    for (i=0; i<len; i++) {
-		rb_ary_push(values, Qnil);
-	    }
-	    v = rb_struct_alloc(klass, values);
-	    v = r_entry(v, arg);
-	    for (i=0; i<len; i++) {
 		slot = r_symbol(arg);
 
 		if (RARRAY_PTR(mem)[i] != ID2SYM(slot)) {
@@ -1165,8 +1274,10 @@
 			     rb_id2name(slot),
 			     rb_id2name(SYM2ID(RARRAY_PTR(mem)[i])));
 		}
-		rb_struct_aset(v, LONG2FIX(i), r_object(arg));
+                rb_ary_push(values, r_object(arg));
 	    }
+            rb_obj_call_init(v, RARRAY_LEN(values), RARRAY_PTR(values));
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1186,6 +1297,7 @@
 	    }
 	    v = rb_funcall(klass, s_load, 1, data);
 	    v = r_entry(v, arg);
+            v = r_leave(v, arg);
 	}
         break;
 
@@ -1208,19 +1320,19 @@
 	    v = r_entry(v, arg);
 	    data = r_object(arg);
 	    rb_funcall(v, s_mload, 1, data);
+            v = r_leave(v, arg);
 	}
         break;
 
       case TYPE_OBJECT:
 	{
-	    VALUE klass = path2class(r_unique(arg));
-
-	    v = rb_obj_alloc(klass);
+            v = obj_alloc_by_path(r_unique(arg), arg);
 	    if (TYPE(v) != T_OBJECT) {
 		rb_raise(rb_eArgError, "dump format error");
 	    }
 	    v = r_entry(v, arg);
 	    r_ivar(v, arg);
+	    v = r_leave(v, arg);
 	}
 	break;
 
@@ -1248,6 +1360,7 @@
                         rb_class2name(klass));
            }
            rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));
+           v = r_leave(v, arg);
        }
        break;
 
@@ -1257,6 +1370,7 @@
 
 	    v = rb_path2class(RSTRING_PTR(str));
 	    v = r_entry(v, arg);
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1266,6 +1380,7 @@
 
 	    v = path2class(RSTRING_PTR(str));
 	    v = r_entry(v, arg);
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1275,6 +1390,7 @@
 
 	    v = path2module(RSTRING_PTR(str));
 	    v = r_entry(v, arg);
+            v = r_leave(v, arg);
 	}
 	break;
 
@@ -1347,6 +1463,7 @@
     }
     arg.src = port;
     arg.offset = 0;
+    arg.compat_tbl = st_init_numtable();
 
     major = r_byte(&arg);
     minor = r_byte(&arg);
@@ -1426,6 +1543,8 @@
 
     rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
     rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
+
+    compat_allocator_tbl = st_init_numtable();
 }
 
 VALUE

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧]