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

ruby-changes:32759

From: nobu <ko1@a...>
Date: Wed, 5 Feb 2014 17:32:17 +0900 (JST)
Subject: [ruby-changes:32759] nobu:r44838 (trunk): marshal.c: refine special instance variables

nobu	2014-02-05 17:32:11 +0900 (Wed, 05 Feb 2014)

  New Revision: 44838

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=44838

  Log:
    marshal.c: refine special instance variables
    
    * marshal.c (w_obj_each, obj_count_ivars): count instance
      variables accurately.
    
    * marshal.c (encoding_name, w_encoding): separate getting encoding
      values and writing them.
    
    * marshal.c (w_symbol, w_ivar, w_objivar, w_object): refine
      special instance variables.

  Modified files:
    trunk/marshal.c
Index: marshal.c
===================================================================
--- marshal.c	(revision 44837)
+++ marshal.c	(revision 44838)
@@ -219,7 +219,8 @@ class2path(VALUE klass) https://github.com/ruby/ruby/blob/trunk/marshal.c#L219
 }
 
 static void w_long(long, struct dump_arg*);
-static void w_encoding(VALUE obj, long num, struct dump_call_arg *arg);
+static void w_encoding(VALUE encname, struct dump_call_arg *arg);
+static VALUE encoding_name(VALUE obj, struct dump_arg *arg);
 
 static void
 w_nbyte(const char *s, long n, struct dump_arg *arg)
@@ -410,7 +411,7 @@ w_symbol(ID id, struct dump_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L411
 {
     VALUE sym;
     st_data_t num;
-    int encidx = -1;
+    VALUE encname;
 
     if (st_lookup(arg->symbols, id, &num)) {
 	w_byte(TYPE_SYMLINK, arg);
@@ -421,10 +422,10 @@ w_symbol(ID id, struct dump_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L422
 	if (!sym) {
 	    rb_raise(rb_eTypeError, "can't dump anonymous ID %"PRIdVALUE, id);
 	}
-	encidx = rb_enc_get_index(sym);
-	if (encidx == rb_usascii_encindex() ||
+	encname = encoding_name(sym, arg);
+	if (NIL_P(encname) ||
 	    rb_enc_str_coderange(sym) == ENC_CODERANGE_7BIT) {
-	    encidx = -1;
+	    encname = Qnil;
 	}
 	else {
 	    w_byte(TYPE_IVAR, arg);
@@ -432,11 +433,12 @@ w_symbol(ID id, struct dump_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L433
 	w_byte(TYPE_SYMBOL, arg);
 	w_bytes(RSTRING_PTR(sym), RSTRING_LEN(sym), arg);
 	st_add_direct(arg->symbols, id, arg->symbols->num_entries);
-	if (encidx != -1) {
+	if (!NIL_P(encname)) {
 	    struct dump_call_arg c_arg;
 	    c_arg.limit = 1;
 	    c_arg.arg = arg;
-	    w_encoding(sym, 0, &c_arg);
+	    w_long(1L, arg);
+	    w_encoding(encname, &c_arg);
 	}
     }
 }
@@ -511,6 +513,8 @@ w_uclass(VALUE obj, VALUE super, struct https://github.com/ruby/ruby/blob/trunk/marshal.c#L513
     }
 }
 
+#define to_be_skipped_id(id) (id == rb_id_encoding() || id == rb_intern("E"))
+
 static int
 w_obj_each(st_data_t key, st_data_t val, st_data_t a)
 {
@@ -518,56 +522,80 @@ w_obj_each(st_data_t key, st_data_t val, https://github.com/ruby/ruby/blob/trunk/marshal.c#L522
     VALUE value = (VALUE)val;
     struct dump_call_arg *arg = (struct dump_call_arg *)a;
 
-    if (id == rb_id_encoding()) return ST_CONTINUE;
-    if (id == rb_intern("E")) return ST_CONTINUE;
+    if (to_be_skipped_id(id)) return ST_CONTINUE;
     w_symbol(id, arg->arg);
     w_object(value, arg->arg, arg->limit);
     return ST_CONTINUE;
 }
 
-static void
-w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
+static int
+obj_count_ivars(st_data_t key, st_data_t val, st_data_t a)
+{
+    ID id = (ID)key;
+    if (!to_be_skipped_id(id)) ++*(st_index_t *)a;
+    return ST_CONTINUE;
+}
+
+static VALUE
+encoding_name(VALUE obj, struct dump_arg *arg)
 {
     int encidx = rb_enc_get_index(obj);
     rb_encoding *enc = 0;
     st_data_t name;
 
     if (encidx <= 0 || !(enc = rb_enc_from_index(encidx))) {
-	w_long(num, arg->arg);
-	return;
+	return Qnil;
     }
-    w_long(num + 1, arg->arg);
 
     /* special treatment for US-ASCII and UTF-8 */
     if (encidx == rb_usascii_encindex()) {
-	w_symbol(rb_intern("E"), arg->arg);
-	w_object(Qfalse, arg->arg, arg->limit + 1);
-	return;
+	return Qfalse;
     }
     else if (encidx == rb_utf8_encindex()) {
+	return Qtrue;
+    }
+
+    if (arg->encodings ?
+	!st_lookup(arg->encodings, (st_data_t)rb_enc_name(enc), &name) :
+	(arg->encodings = st_init_strcasetable(), 1)) {
+	name = (st_data_t)rb_str_new_cstr(rb_enc_name(enc));
+	st_insert(arg->encodings, (st_data_t)rb_enc_name(enc), name);
+    }
+    return (VALUE)name;
+}
+
+static void
+w_encoding(VALUE encname, struct dump_call_arg *arg)
+{
+    switch (encname) {
+      case Qfalse:
+      case Qtrue:
 	w_symbol(rb_intern("E"), arg->arg);
-	w_object(Qtrue, arg->arg, arg->limit + 1);
+	w_object(encname, arg->arg, arg->limit + 1);
+      case Qnil:
 	return;
     }
-
     w_symbol(rb_id_encoding(), arg->arg);
-    do {
-	if (!arg->arg->encodings)
-	    arg->arg->encodings = st_init_strcasetable();
-	else if (st_lookup(arg->arg->encodings, (st_data_t)rb_enc_name(enc), &name))
-	    break;
-	name = (st_data_t)rb_str_new2(rb_enc_name(enc));
-	st_insert(arg->arg->encodings, (st_data_t)rb_enc_name(enc), name);
-    } while (0);
-    w_object(name, arg->arg, arg->limit + 1);
+    w_object(encname, arg->arg, arg->limit + 1);
 }
 
-static void
-w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
+static st_index_t
+has_ivars(VALUE obj, VALUE encname, st_table **ivtbl)
 {
-    long num = tbl ? tbl->num_entries : 0;
+    st_index_t num = !NIL_P(encname);
+
+    *ivtbl = rb_generic_ivar_table(obj);
+    if (*ivtbl) {
+	st_foreach_safe(*ivtbl, obj_count_ivars, (st_data_t)&num);
+    }
+    return num;
+}
 
-    w_encoding(obj, num, arg);
+static void
+w_ivar(st_index_t num, st_table *tbl, VALUE encname, struct dump_call_arg *arg)
+{
+    w_long(num, arg->arg);
+    w_encoding(encname, arg);
     if (tbl) {
 	st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
     }
@@ -586,7 +614,7 @@ w_objivar(VALUE obj, struct dump_call_ar https://github.com/ruby/ruby/blob/trunk/marshal.c#L614
         if (ptr[i] != Qundef)
             num += 1;
 
-    w_encoding(obj, num, arg);
+    w_long(num, arg->arg);
     if (num != 0) {
         rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
     }
@@ -598,9 +626,8 @@ w_object(VALUE obj, struct dump_arg *arg https://github.com/ruby/ruby/blob/trunk/marshal.c#L626
     struct dump_call_arg c_arg;
     st_table *ivtbl = 0;
     st_data_t num;
-    int hasiv = 0;
-#define has_ivars(obj, ivtbl) ((((ivtbl) = rb_generic_ivar_table(obj)) != 0) || \
-			       (!SPECIAL_CONST_P(obj) && !ENCODING_IS_ASCII8BIT(obj)))
+    st_index_t hasiv = 0;
+    VALUE encname = Qnil;
 
     if (limit == 0) {
 	rb_raise(rb_eArgError, "exceed depth limit");
@@ -663,7 +690,8 @@ w_object(VALUE obj, struct dump_arg *arg https://github.com/ruby/ruby/blob/trunk/marshal.c#L690
 	}
 	if (rb_obj_respond_to(obj, s_dump, TRUE)) {
             st_table *ivtbl2 = 0;
-            int hasiv2;
+	    st_index_t hasiv2;
+	    VALUE encname2;
 
 	    v = INT2NUM(limit);
 	    v = rb_funcall2(obj, s_dump, 1, &v);
@@ -671,18 +699,18 @@ w_object(VALUE obj, struct dump_arg *arg https://github.com/ruby/ruby/blob/trunk/marshal.c#L699
 	    if (!RB_TYPE_P(v, T_STRING)) {
 		rb_raise(rb_eTypeError, "_dump() must return string");
 	    }
-	    hasiv = has_ivars(obj, ivtbl);
-	    if (hasiv) w_byte(TYPE_IVAR, arg);
-	    if ((hasiv2 = has_ivars(v, ivtbl2)) != 0 && !hasiv) {
-		w_byte(TYPE_IVAR, arg);
+	    hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivtbl);
+	    hasiv2 = has_ivars(v, (encname2 = encoding_name(v, arg)), &ivtbl2);
+	    if (hasiv2) {
+		hasiv = hasiv2;
+		ivtbl = ivtbl2;
+		encname = encname2;
 	    }
+	    if (hasiv) w_byte(TYPE_IVAR, arg);
 	    w_class(TYPE_USERDEF, obj, arg, FALSE);
 	    w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
-            if (hasiv2) {
-		w_ivar(v, ivtbl2, &c_arg);
-            }
-            else if (hasiv) {
-		w_ivar(obj, ivtbl, &c_arg);
+	    if (hasiv) {
+		w_ivar(hasiv, ivtbl, encname, &c_arg);
 	    }
             st_add_direct(arg->data, obj, arg->data->num_entries);
 	    return;
@@ -690,7 +718,7 @@ w_object(VALUE obj, struct dump_arg *arg https://github.com/ruby/ruby/blob/trunk/marshal.c#L718
 
         st_add_direct(arg->data, obj, arg->data->num_entries);
 
-	hasiv = has_ivars(obj, ivtbl);
+	hasiv = has_ivars(obj, (encname = encoding_name(obj, arg)), &ivtbl);
         {
             st_data_t compat_data;
             rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
@@ -855,7 +883,7 @@ w_object(VALUE obj, struct dump_arg *arg https://github.com/ruby/ruby/blob/trunk/marshal.c#L883
 	RB_GC_GUARD(obj);
     }
     if (hasiv) {
-	w_ivar(obj, ivtbl, &c_arg);
+	w_ivar(hasiv, ivtbl, encname, &c_arg);
     }
 }
 

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

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