summaryrefslogtreecommitdiffstats
path: root/marshal.c
diff options
context:
space:
mode:
Diffstat (limited to 'marshal.c')
-rw-r--r--marshal.c66
1 files changed, 56 insertions, 10 deletions
diff --git a/marshal.c b/marshal.c
index 950a1b31d..1d8b5afa8 100644
--- a/marshal.c
+++ b/marshal.c
@@ -47,7 +47,7 @@ shortlen(long len, BDIGIT *ds)
#endif
#define MARSHAL_MAJOR 4
-#define MARSHAL_MINOR 8
+#define MARSHAL_MINOR 9
#define TYPE_NIL '0'
#define TYPE_TRUE 'T'
@@ -73,6 +73,7 @@ shortlen(long len, BDIGIT *ds)
#define TYPE_MODULE 'm'
#define TYPE_SYMBOL ':'
+#define TYPE_SYMBOL2 ','
#define TYPE_SYMLINK ';'
#define TYPE_IVAR 'I'
@@ -304,7 +305,7 @@ w_float(double d, struct dump_arg *arg)
static void
w_symbol(ID id, struct dump_arg *arg)
{
- const char *sym = rb_id2name(id);
+ const char *sym;
st_data_t num;
if (st_lookup(arg->symbols, id, &num)) {
@@ -312,8 +313,22 @@ w_symbol(ID id, struct dump_arg *arg)
w_long((long)num, arg);
}
else {
- w_byte(TYPE_SYMBOL, arg);
- w_bytes(sym, strlen(sym), arg);
+ if (rb_is_instance2_id(id)) {
+ VALUE klass;
+ volatile VALUE path;
+
+ id = rb_decompose_ivar2(id, &klass);
+ path = class2path(klass);
+ w_byte(TYPE_SYMBOL2, arg);
+ sym = rb_id2name(id);
+ w_bytes(sym, strlen(sym), arg);
+ w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
+ }
+ else {
+ sym = rb_id2name(id);
+ w_byte(TYPE_SYMBOL, arg);
+ w_bytes(sym, strlen(sym), arg);
+ }
st_add_direct(arg->symbols, id, arg->symbols->num_entries);
}
}
@@ -360,12 +375,14 @@ w_extended(VALUE klass, struct dump_arg *arg, int check)
static void
w_class(char type, VALUE obj, struct dump_arg *arg, int check)
{
+ volatile VALUE p;
char *path;
VALUE klass = CLASS_OF(obj);
w_extended(klass, arg, check);
w_byte(type, arg);
- path = RSTRING_PTR(class2path(rb_class_real(klass)));
+ p = class2path(rb_class_real(klass));
+ path = RSTRING_PTR(p);
w_unique(path, arg);
}
@@ -490,7 +507,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
}
w_byte(TYPE_CLASS, arg);
{
- VALUE path = class2path(obj);
+ volatile VALUE path = class2path(obj);
w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
}
break;
@@ -738,7 +755,9 @@ struct load_arg {
int taint;
};
+static VALUE r_entry(VALUE v, struct load_arg *arg);
static VALUE r_object(struct load_arg *arg);
+static VALUE path2class(const char *path);
static int
r_byte(struct load_arg *arg)
@@ -855,10 +874,24 @@ r_symlink(struct load_arg *arg)
static ID
r_symreal(struct load_arg *arg)
{
- ID id;
volatile VALUE s = r_bytes(arg);
+ ID id = rb_intern(RSTRING_PTR(s));
+
+ st_insert(arg->symbols, arg->symbols->num_entries, id);
+
+ return id;
+}
+
+static ID
+r_symivar2(struct load_arg *arg)
+{
+ volatile VALUE s = r_bytes(arg);
+ ID id = rb_intern(RSTRING_PTR(s));
+ VALUE klass;
- id = rb_intern(RSTRING_PTR(s));
+ s = r_bytes(arg);
+ klass = r_entry(path2class(RSTRING_PTR(s)), arg);
+ id = rb_compose_ivar2(id, klass);
st_insert(arg->symbols, arg->symbols->num_entries, id);
return id;
@@ -867,10 +900,19 @@ r_symreal(struct load_arg *arg)
static ID
r_symbol(struct load_arg *arg)
{
- if (r_byte(arg) == TYPE_SYMLINK) {
+ int type;
+
+ switch ((type = r_byte(arg))) {
+ case TYPE_SYMBOL:
+ return r_symreal(arg);
+ case TYPE_SYMBOL2:
+ return r_symivar2(arg);
+ case TYPE_SYMLINK:
return r_symlink(arg);
+ default:
+ rb_raise(rb_eArgError, "dump format error(0x%x)", type);
+ break;
}
- return r_symreal(arg);
}
static const char*
@@ -1274,6 +1316,10 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = ID2SYM(r_symreal(arg));
break;
+ case TYPE_SYMBOL2:
+ v = ID2SYM(r_symivar2(arg));
+ break;
+
case TYPE_SYMLINK:
v = ID2SYM(r_symlink(arg));
break;