cvsuser     04/11/11 05:26:34

  Modified:    classes  parrotclass.pmc parrotobject.pmc
               include/parrot pmc_freeze.h
               src      pmc_freeze.c
               t/pmc    freeze.t
  Log:
  freeze_thaw a class 7 - and objects
  * create PMCs a bit later during thaw
  * and thaw them earlier so that existing classes are handled properly
  * use depth first now for freeze/thaw
  * create a separate list for PMCs that need thawfinish
  
  Revision  Changes    Path
  1.30      +12 -16    parrot/classes/parrotclass.pmc
  
  Index: parrotclass.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/classes/parrotclass.pmc,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- parrotclass.pmc   10 Nov 2004 15:54:01 -0000      1.29
  +++ parrotclass.pmc   11 Nov 2004 13:26:29 -0000      1.30
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: parrotclass.pmc,v 1.29 2004/11/10 15:54:01 leo Exp $
  +$Id: parrotclass.pmc,v 1.30 2004/11/11 13:26:29 leo Exp $
   
   =head1 NAME
   
  @@ -217,6 +217,7 @@
               STRING *class_name;
               INTVAL new_type;
               PMC *ar;
  +            PMC *real_class;
   
               /* thaw class name */
               class_name = io->vtable->shift_string(INTERP, io);
  @@ -226,19 +227,20 @@
                */
               new_type = pmc_type(INTERP, class_name);
               if (new_type > enum_type_undef) {
  +                real_class = Parrot_class_lookup(INTERP, class_name);
  +                info->extra = real_class;
                   info->extra_flags = EXTRA_CLASS_EXISTS;
  -                *info->thaw_ptr = SELF =
  -                    Parrot_class_lookup(INTERP, class_name);
               }
               else {
  +                real_class = SELF;
                   SELF.init();
                   Parrot_new_class(INTERP, SELF, class_name);
               }
               /* make room for thawed arrays */
  -            if (PMC_int_val(SELF) == PCD_MAX) {
  +            if (PMC_int_val(real_class) == PCD_MAX) {
                   PMC **class_data;
  -                resize_attrib_array(SELF, PCD_MAX + 2);
  -                class_data = (PMC **)PMC_data(SELF);
  +                resize_attrib_array(real_class, PCD_MAX + 2);
  +                class_data = (PMC **)PMC_data(real_class);
                   class_data[PCD_MAX] = NULL;
                   class_data[PCD_MAX + 1] = NULL;
               }
  @@ -248,18 +250,12 @@
   
       void thawfinish(visit_info *info) {
           INTVAL i, n, nold;
  -        PMC * class = SELF;
  +        PMC * class;
           PMC *parents, *attribs, *old;
  -        int ignore = 0; /* XXX */
  -        PMC **class_data = (PMC **)PMC_data(SELF);
  +        PMC **class_data;
   
  -        /*
  -         * we now have two plain arrays: parents and attributes
  -         * TODO if class did exists compare these with the
  -         *      information in the class
  -         * TODO don't thaw directly into class array - this destroys
  -         *      existing classes
  -         */
  +        class = SELF;
  +        class_data = (PMC**)(PMC_data(class));
   
           old = class_data[PCD_PARENTS];
           nold = VTABLE_elements(INTERP, old);
  
  
  
  1.34      +24 -3     parrot/classes/parrotobject.pmc
  
  Index: parrotobject.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/classes/parrotobject.pmc,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- parrotobject.pmc  9 Nov 2004 15:07:26 -0000       1.33
  +++ parrotobject.pmc  11 Nov 2004 13:26:29 -0000      1.34
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: parrotobject.pmc,v 1.33 2004/11/09 15:07:26 leo Exp $
  +$Id: parrotobject.pmc,v 1.34 2004/11/11 13:26:29 leo Exp $
   
   =head1 NAME
   
  @@ -190,6 +190,7 @@
   
           /* 1) visit class */
           pos = class_data + POD_CLASS;
  +        info->thaw_ptr = pos;
           (info->visit_pmc_now)(interpreter, *pos, info);
   
           /* 2) visit the attributes */
  @@ -200,12 +201,32 @@
           }
       }
       void freeze(visit_info *info) {
  -        Parrot_default_freeze(INTERP, SELF, info);
  +        IMAGE_IO *io = info->image_io;
  +        io->vtable->push_integer(INTERP, io, ATTRIB_COUNT(SELF));
       }
  +
       void thaw(visit_info *info) {
  -        Parrot_default_thaw(INTERP, SELF, info);
  +        IMAGE_IO *io = info->image_io;
  +        if (info->extra_flags == EXTRA_IS_PROP_HASH) {
  +            SUPER(info);
  +        }
  +        else if (info->extra_flags == EXTRA_IS_NULL) {
  +            INTVAL n = io->vtable->shift_integer(INTERP, io);
  +            set_attrib_array_size(SELF, n);
  +            ATTRIB_COUNT(SELF) = n;
  +        }
       }
  +
       void thawfinish(visit_info *info) {
  +        PMC *class = get_attrib_num((SLOTTYPE *)PMC_data(SELF), POD_CLASS);
  +        PMC *class_name = get_attrib_num((SLOTTYPE *)PMC_data(class),
  +            PCD_CLASS_NAME);
  +        PMC *vtable_pmc = get_attrib_num((SLOTTYPE *)PMC_data(class),
  +                PCD_OBJECT_VTABLE);
  +        SELF->vtable = PMC_struct_val(vtable_pmc);
  +        set_attrib_num(SELF, PMC_data(SELF), POD_CLASS_NAME, class_name);
  +        set_attrib_flags(SELF);
  +        PObj_is_object_SET(SELF);
       }
   }
   
  
  
  
  1.9       +2 -1      parrot/include/parrot/pmc_freeze.h
  
  Index: pmc_freeze.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/pmc_freeze.h,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- pmc_freeze.h      9 Nov 2004 15:07:28 -0000       1.8
  +++ pmc_freeze.h      11 Nov 2004 13:26:32 -0000      1.9
  @@ -1,7 +1,7 @@
   /* pmc_freeze.h
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: pmc_freeze.h,v 1.8 2004/11/09 15:07:28 leo Exp $
  + *     $Id: pmc_freeze.h,v 1.9 2004/11/11 13:26:32 leo Exp $
    *  Overview:
    *     PMC freeze and thaw interface
    *  Data Structure and Algorithms:
  @@ -76,6 +76,7 @@
       UINTVAL             id;             /* freze ID of PMC */
       void*               extra;          /* PMC specific */
       extra_flags_enum    extra_flags;    /* concerning to extra */
  +    PMC*                thaw_result;    /* 1st thawed */
       IMAGE_IO            *image_io;
   } visit_info;
   
  
  
  
  1.30      +91 -80    parrot/src/pmc_freeze.c
  
  Index: pmc_freeze.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/pmc_freeze.c,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- pmc_freeze.c      10 Nov 2004 15:01:16 -0000      1.29
  +++ pmc_freeze.c      11 Nov 2004 13:26:33 -0000      1.30
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: pmc_freeze.c,v 1.29 2004/11/10 15:01:16 leo Exp $
  +$Id: pmc_freeze.c,v 1.30 2004/11/11 13:26:33 leo Exp $
   
   =head1 NAME
   
  @@ -788,6 +788,9 @@
           return;
       }
       type = pmc->vtable->base_type;
  +
  +    if (PObj_is_object_TEST(pmc))
  +        type = enum_class_ParrotObject;
       if (seen) {
           if (info->extra_flags) {
               id |= 3;
  @@ -909,38 +912,28 @@
   */
   
   PARROT_INLINE static PMC*
  -thaw_create_pmc(Parrot_Interp interpreter, PMC *pmc, visit_info *info,
  +thaw_create_pmc(Parrot_Interp interpreter, visit_info *info,
           INTVAL type)
   {
  -    if (!PMC_IS_NULL(pmc)) { /* first thawed PMC - just attach vtable */
  -        pmc->vtable = Parrot_base_vtables[type];
  -        pmc_add_ext(interpreter, pmc);
  -    }
  -    else {      /* create a new header */
  -        switch (info->what) {
  -            case VISIT_THAW_NORMAL:
  -                pmc = pmc_new_noinit(interpreter, type);
  -                break;
  -            case VISIT_THAW_CONSTANTS:
  -                pmc = constant_pmc_new_noinit(interpreter, type);
  -                break;
  -            default:
  -                internal_exception(1, "Illegal visit_next type");
  -                break;
  -        }
  -        assert(info->thaw_ptr);
  -        if (info->container) {
  -            DOD_WRITE_BARRIER(interpreter, info->container, NULL, pmc);
  -        }
  -        *info->thaw_ptr = pmc;
  +    PMC *pmc = NULL;
  +    switch (info->what) {
  +        case VISIT_THAW_NORMAL:
  +            pmc = pmc_new_noinit(interpreter, type);
  +            break;
  +        case VISIT_THAW_CONSTANTS:
  +            pmc = constant_pmc_new_noinit(interpreter, type);
  +            break;
  +        default:
  +            internal_exception(1, "Illegal visit_next type");
  +            break;
       }
       return pmc;
   }
   
   /*
   
  -=item C<PARROT_INLINE static PMC*
  -do_thaw(Parrot_Interp interpreter, PMC* pmc, visit_info *info, int *seen)>
  +=item C<PARROT_INLINE static void
  +do_thaw(Parrot_Interp interpreter, PMC* pmc, visit_info *info)>
   
   Called by C<visit_todo_list_thaw()> to thaw and return a PMC.
   
  @@ -950,8 +943,8 @@
   
   */
   
  -PARROT_INLINE static PMC*
  -do_thaw(Parrot_Interp interpreter, PMC* pmc, visit_info *info, int *seen)
  +PARROT_INLINE static void
  +do_thaw(Parrot_Interp interpreter, PMC* pmc, visit_info *info)
   {
       UINTVAL id;
       INTVAL type;
  @@ -963,9 +956,11 @@
       if (!id) {
           /* got a NULL PMC */
           pmc = PMCNULL;
  -        *info->thaw_ptr = pmc;
  -        *seen = 1;
  -        return pmc;
  +        if (!info->thaw_result)
  +            info->thaw_result = pmc;
  +        else
  +            *info->thaw_ptr = pmc;
  +        return;
       }
   
       pos = list_get(interpreter, PMC_data(info->id_list), id, enum_type_PMC);
  @@ -977,10 +972,9 @@
               pos = NULL;
       }
       if (pos) {
  -        *seen = 1;
           if (info->extra_flags) {
               VTABLE_thaw(interpreter, pmc, info);
  -            return pmc;
  +            return;
           }
   #if FREEZE_USE_NEXT_FOR_GC
           /*
  @@ -998,23 +992,34 @@
   #endif
           /*
            * that's a duplicate
  -          if (info->container)
  -              DOD_WRITE_BARRIER(interpreter, info->container, NULL, pmc);
  -        */
  +         if (info->container)
  +         DOD_WRITE_BARRIER(interpreter, info->container, NULL, pmc);
  +         */
           *info->thaw_ptr = pmc;
  -        return pmc;
  +        return;
       }
   
       assert(!must_have_seen);
  -    *seen = 0;
  -    pmc = thaw_create_pmc(interpreter, pmc, info, type);
  +    pmc = thaw_create_pmc(interpreter, info, type);
   
  -    info->visit_action = pmc->vtable->thaw;
  +    VTABLE_thaw(interpreter, pmc, info);
  +    if (info->extra_flags == EXTRA_CLASS_EXISTS) {
  +        pmc = info->extra;
  +        info->extra = NULL;
  +        info->extra_flags = 0;
  +    }
  +    if (!info->thaw_result)
  +        info->thaw_result = pmc;
  +    else {
  +        if (info->container) {
  +            DOD_WRITE_BARRIER(interpreter, info->container, NULL, pmc);
  +        }
  +        *info->thaw_ptr = pmc;
  +    }
       list_assign(interpreter, PMC_data(info->id_list), id, pmc, 
enum_type_PMC);
  -    /* remember nested aggregates breadth first */
  +    /* remember nested aggregates depth first */
       if (pmc->pmc_ext)
  -        list_push(interpreter, PMC_data(info->todo), pmc, enum_type_PMC);
  -    return pmc;
  +        list_unshift(interpreter, PMC_data(info->todo), pmc, enum_type_PMC);
   }
   
   #if ARENA_DOD_FLAGS
  @@ -1213,7 +1218,7 @@
       hash_put(interpreter, PMC_struct_val(info->seen), pmc, (void*)*id);
       /* remember containers */
       if (pmc->pmc_ext)
  -        list_push(interpreter, PMC_data(info->todo), pmc, enum_type_PMC);
  +        list_unshift(interpreter, PMC_data(info->todo), pmc, enum_type_PMC);
       return 0;
   }
   
  @@ -1236,6 +1241,7 @@
   {
       UINTVAL id;
       int seen = next_for_GC_seen(interpreter, pmc, info, &id);
  +    internal_exception(1, "todo convert to depth first");
       do_action(interpreter, pmc, info, seen, id);
       /*
        * TODO probe for class methods that override the default.
  @@ -1292,9 +1298,7 @@
   visit_todo_list_thaw(Parrot_Interp interpreter, PMC* old, visit_info* info)
   {
       int seen;
  -    PMC* pmc = do_thaw(interpreter, old, info, &seen);
  -    if (!seen)
  -        (info->visit_action)(interpreter, pmc, info);
  +    do_thaw(interpreter, old, info);
   }
   
   /*
  @@ -1337,35 +1341,48 @@
   
   */
   
  -static PMC*
  +extern void
  +Parrot_default_thawfinish(Interp* interpreter, PMC* pmc, visit_info *info);
  +
  +static void
   visit_loop_todo_list(Parrot_Interp interpreter, PMC *current,
           visit_info *info)
   {
       List *todo = PMC_data(info->todo);
  +    PMC *finish_list_pmc;
       int i, n;
  -    PMC *ret = current;
  +    List *finish_list;
  +    int thawing;
  +    int finished_first = 0;
  +
  +    thawing =  info->what == VISIT_THAW_CONSTANTS ||
  +            info->what == VISIT_THAW_NORMAL;
  +    if (thawing) {
  +        /*
  +         * create a list that contains PMCs that need thawfinish
  +         */
  +        finish_list_pmc = pmc_new(interpreter, enum_class_Array);
  +        finish_list = PMC_data(finish_list_pmc);
  +    }
   
       (info->visit_pmc_now)(interpreter, current, info);
       /*
        * can't cache upper limit, visit may append items
        */
  -    i = 0;
   again:
  -    for (; i < (int)list_length(interpreter, todo); ++i) {
  -        current = *(PMC**)list_get(interpreter, todo, i, enum_type_PMC);
  -        if (info->extra_flags == EXTRA_CLASS_EXISTS) {
  -            int is_first = (ret == current);
  -            info->extra_flags = 0;
  -            current = *info->thaw_ptr;
  -            if (is_first)
  -                ret = current;
  -            info->thaw_ptr = NULL;
  -            list_assign(interpreter, todo, i, current, enum_type_PMC);
  -        }
  +    for (; (int)list_length(interpreter, todo); ) {
  +        current = *(PMC**)list_shift(interpreter, todo, enum_type_PMC);
           VTABLE_visit(interpreter, current, info);
  +        if (thawing) {
  +            if (current == info->thaw_result)
  +                finished_first = 1;
  +            if (current->vtable && current->vtable->thawfinish !=
  +                    Parrot_default_thawfinish)
  +                list_unshift(interpreter, finish_list, current, 
enum_type_PMC);
  +        }
       }
  -    if (info->what == VISIT_THAW_CONSTANTS ||
  -            info->what == VISIT_THAW_NORMAL) {
  +
  +    if (thawing) {
           /*
            * if image isn't consumed, there are some extra data to thaw
            */
  @@ -1376,23 +1393,22 @@
           /*
            * on thawing call thawfinish for each processed PMC
            */
  -        if (!current->vtable) {
  -            /* the first created (passed) PMC was NULL -
  -             * return a NULL PMC
  +        if (!finished_first) {
  +            /*
  +             * the first create PMC might not be in the list,
  +             * if it has no pmc_ext
                */
  -            ret = PMCNULL;
  +            list_unshift(interpreter, finish_list,
  +                    info->thaw_result, enum_type_PMC);
           }
  -        else
  -            if (!PMC_IS_NULL(current))
  -                VTABLE_thawfinish(interpreter, current, info);
  -        n = (int)list_length(interpreter, todo);
  +        n = (int)list_length(interpreter, finish_list);
           for (i = 0; i < n ; ++i) {
  -            current = *(PMC**)list_get(interpreter, todo, i, enum_type_PMC);
  +            current = *(PMC**)list_get(interpreter, finish_list, i,
  +                    enum_type_PMC);
               if (!PMC_IS_NULL(current))
                   VTABLE_thawfinish(interpreter, current, info);
           }
       }
  -    return ret;
   }
   
   /*
  @@ -1449,7 +1465,6 @@
   run_thaw(Parrot_Interp interpreter, STRING* image, visit_enum_type what)
   {
       visit_info info;
  -    PMC *n = NULL;
       int dod_block = 0;
       UINTVAL bufused;
   
  @@ -1472,15 +1487,11 @@
       info.visit_pmc_now = visit_todo_list_thaw;
       info.visit_pmc_later = add_pmc_todo_list;
   
  -    /*
  -     * create first PMC, we want to return it
  -     */
  -    n = new_pmc_header(interpreter, 0);
  -    info.thaw_ptr = &n;
  +    info.thaw_result = NULL;
       /*
        * run thaw loop
        */
  -    n = visit_loop_todo_list(interpreter, n, &info);
  +    visit_loop_todo_list(interpreter, NULL, &info);
       /*
        * thaw does "consume" the image string by incrementing strstart
        * and decrementing bufused - restore that
  @@ -1493,7 +1504,7 @@
           Parrot_unblock_DOD(interpreter);
           Parrot_unblock_GC(interpreter);
       }
  -    return n;
  +    return info.thaw_result;
   }
   
   /*
  
  
  
  1.19      +87 -2     parrot/t/pmc/freeze.t
  
  Index: freeze.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/freeze.t,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- freeze.t  10 Nov 2004 15:54:02 -0000      1.18
  +++ freeze.t  11 Nov 2004 13:26:34 -0000      1.19
  @@ -1,6 +1,6 @@
   #! perl -w
   # Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -# $Id: freeze.t,v 1.18 2004/11/10 15:54:02 leo Exp $
  +# $Id: freeze.t,v 1.19 2004/11/11 13:26:34 leo Exp $
   
   =head1 NAME
   
  @@ -16,7 +16,7 @@
   
   =cut
   
  -use Parrot::Test tests => 21;
  +use Parrot::Test tests => 23;
   use Test::More;
   
   END { unlink "temp.fpmc"; };
  @@ -612,3 +612,88 @@
   ok 6
   OUTPUT
   
  +output_is(<<'CODE', <<'OUTPUT', "thaw object w attr into same interpreter");
  +    newclass P10, "Foo"
  +    addattribute P10, ".aa"
  +    addattribute P10, ".bb"
  +    find_type I4, "Foo"
  +    new P10, I4
  +    print S10
  +    freeze S3, P10
  +    open P3, "temp.fpmc", ">"
  +    print P3, S3
  +    close P3
  +    print "ok 1\n"
  +
  +    thaw P5, S3
  +    print "ok 2\n"
  +    classname S10, P5
  +    print S10
  +    print "\n"
  +
  +    print "ok 3\n"
  +    classoffset I5, P5, S10
  +    new P6, .PerlString
  +    set P6, "ok 5\n"
  +    setattribute P5, "Foo\0.aa", P6
  +    new P6, .PerlString
  +    set P6, "ok 6\n"
  +    setattribute P5, "Foo\0.bb", P6
  +    print "ok 4\n"
  +    getattribute P7, P5, I5
  +    print P7
  +    inc I5
  +    getattribute P7, P5, I5
  +    print P7
  +    end
  +CODE
  +ok 1
  +ok 2
  +Foo
  +ok 3
  +ok 4
  +ok 5
  +ok 6
  +OUTPUT
  +
  +output_is(<<'CODE', <<'OUTPUT', "thaw object w attr into new interpreter");
  +    set S3, "temp.fpmc"
  +    .include "stat.pasm"
  +    stat I0, S3, .STAT_FILESIZE
  +    gt I0, 1, ok1
  +    print "stat failed\n"
  +    exit 1
  +ok1:
  +    open P3, S3, "<"
  +    read S3, P3, I0
  +    close P3
  +
  +    thaw P5, S3
  +    print "ok 2\n"
  +    classname S10, P5
  +    print S10
  +    print "\n"
  +
  +    print "ok 3\n"
  +    classoffset I5, P5, S10
  +    new P6, .PerlString
  +    set P6, "ok 5\n"
  +    setattribute P5, "Foo\0.aa", P6
  +    new P6, .PerlString
  +    set P6, "ok 6\n"
  +    setattribute P5, "Foo\0.bb", P6
  +    print "ok 4\n"
  +    getattribute P7, P5, I5
  +    print P7
  +    inc I5
  +    getattribute P7, P5, I5
  +    print P7
  +    end
  +CODE
  +ok 2
  +Foo
  +ok 3
  +ok 4
  +ok 5
  +ok 6
  +OUTPUT
  
  
  

Reply via email to