diff --git a/MANIFEST b/MANIFEST index 2a74e32e42..6ef5f792f2 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1428,6 +1428,7 @@ src/pmc/handle.pmc [devel]src src/pmc/hash.pmc [devel]src src/pmc/hashiterator.pmc [devel]src src/pmc/hashiteratorkey.pmc [devel]src +src/pmc/imageio.pmc [devel]src src/pmc/integer.pmc [devel]src src/pmc/iterator.pmc [devel]src src/pmc/key.pmc [devel]src diff --git a/PBC_COMPAT b/PBC_COMPAT index 346a414428..4b9d1ad24c 100644 --- a/PBC_COMPAT +++ b/PBC_COMPAT @@ -27,6 +27,7 @@ # please insert tab separated entries at the top of the list +6.2 2010.01.31 cotto serialization-related changes to ParrotInterpreter 6.1 2010.01.30 whiteknight remove Array PMC 6.0 2010.01.19 chromatic released 2.0.0 5.1 2009.08.06 cotto remove branch_cs opcode diff --git a/include/parrot/pmc_freeze.h b/include/parrot/pmc_freeze.h index bb4666084c..93fac8ed81 100644 --- a/include/parrot/pmc_freeze.h +++ b/include/parrot/pmc_freeze.h @@ -14,7 +14,7 @@ #define PARROT_PMC_FREEZE_H_GUARD struct _visit_info; -typedef void (*visit_f)(PARROT_INTERP, ARGIN_NULLOK(PMC*), ARGIN(struct _visit_info*)); +typedef void (*visit_f)(PARROT_INTERP, ARGIN_NULLOK(PMC*), ARGIN(PMC*)); typedef enum { VISIT_HOW_PMC_TO_VISITOR = 0x00, /* push to visitor */ @@ -40,53 +40,11 @@ typedef enum { #define VISIT_THAW_NORMAL (VISIT_HOW_VISITOR_TO_PMC | VISIT_WHAT_PMC) #define VISIT_THAW_CONSTANTS VISIT_THAW_NORMAL -struct _visit_info; -typedef INTVAL (*get_integer_f) (PARROT_INTERP, struct _visit_info*); -typedef void (*push_integer_f) (PARROT_INTERP, struct _visit_info*, INTVAL); -typedef void (*push_string_f) (PARROT_INTERP, struct _visit_info*, STRING*); -typedef void (*push_number_f) (PARROT_INTERP, struct _visit_info*, FLOATVAL); -typedef void (*push_pmc_f) (PARROT_INTERP, struct _visit_info*, PMC*); -typedef INTVAL (*shift_integer_f) (PARROT_INTERP, struct _visit_info*); -typedef STRING* (*shift_string_f) (PARROT_INTERP, struct _visit_info*); -typedef FLOATVAL (*shift_number_f) (PARROT_INTERP, struct _visit_info*); -typedef PMC* (*shift_pmc_f) (PARROT_INTERP, struct _visit_info*); - -typedef struct _image_funcs { - get_integer_f get_integer; - push_integer_f push_integer; - push_string_f push_string; - push_number_f push_float; - push_pmc_f push_pmc; - shift_integer_f shift_integer; - shift_string_f shift_string; - shift_number_f shift_float; - shift_pmc_f shift_pmc; -} image_funcs; - typedef enum { EXTRA_IS_NULL, EXTRA_IS_PROP_HASH, } extra_flags_enum; -typedef struct _visit_info { - visit_f visit_pmc_now; - size_t pos; /* current read/write position in buffer */ - Buffer *buffer; - size_t input_length; /* */ - INTVAL what; - PMC **thaw_ptr; /* where to thaw a new PMC */ - PMC *seen; /* seen hash */ - PMC *todo; /* todo list */ - PMC *id_list; /* seen list used by thaw */ - UINTVAL id; /* freze ID of PMC */ - INTVAL extra_flags; /* concerning to extra */ - struct PackFile *pf; - const image_funcs *vtable; - struct _visit_info *image_io; /* dummy backwards-compat pointer. */ -} visit_info; - -#define IMAGE_IO visit_info - #define VISIT_PMC(interp, visit, pmc) do {\ const INTVAL _visit_pmc_flags = VTABLE_get_integer((interp), (visit)); \ if (_visit_pmc_flags & VISIT_WHAT_PMC) { \ diff --git a/src/hash.c b/src/hash.c index f306b6e246..bb8fb7343d 100644 --- a/src/hash.c +++ b/src/hash.c @@ -55,7 +55,7 @@ static void expand_hash(PARROT_INTERP, ARGMOD(Hash *hash)) static void hash_freeze(PARROT_INTERP, ARGIN(const Hash * const hash), - ARGMOD(visit_info *info)) + ARGMOD(PMC *info)) __attribute__nonnull__(1) __attribute__nonnull__(2) __attribute__nonnull__(3) @@ -63,7 +63,7 @@ static void hash_freeze(PARROT_INTERP, static void hash_thaw(PARROT_INTERP, ARGMOD(Hash *hash), - ARGMOD(visit_info *info)) + ARGMOD(PMC *info)) __attribute__nonnull__(1) __attribute__nonnull__(2) __attribute__nonnull__(3) @@ -541,7 +541,7 @@ parrot_mark_hash_both(PARROT_INTERP, ARGIN(Hash *hash)) /* -=item C +=item C Visits the contents of a hash during freeze/thaw. @@ -552,7 +552,7 @@ C is the visit info, (see include/parrot/pmc_freeze.h>). */ static void -hash_thaw(PARROT_INTERP, ARGMOD(Hash *hash), ARGMOD(visit_info *info)) +hash_thaw(PARROT_INTERP, ARGMOD(Hash *hash), ARGMOD(PMC *info)) { ASSERT_ARGS(hash_thaw) @@ -608,8 +608,8 @@ hash_thaw(PARROT_INTERP, ARGMOD(Hash *hash), ARGMOD(visit_info *info)) /* -=item C +=item C Freezes hash into a string. @@ -623,7 +623,7 @@ Use by parrot_hash_visit. */ static void -hash_freeze(PARROT_INTERP, ARGIN(const Hash * const hash), ARGMOD(visit_info *info)) +hash_freeze(PARROT_INTERP, ARGIN(const Hash * const hash), ARGMOD(PMC *info)) { ASSERT_ARGS(hash_freeze) size_t i; @@ -677,7 +677,7 @@ void parrot_hash_visit(PARROT_INTERP, ARGMOD(Hash *hash), ARGMOD(void *pinfo)) { ASSERT_ARGS(parrot_hash_visit) - visit_info* const info = (visit_info*) pinfo; + PMC* const info = (PMC*) pinfo; switch (VTABLE_get_integer(interp, info)) { case VISIT_THAW_NORMAL: diff --git a/src/pmc/class.pmc b/src/pmc/class.pmc index 4eace958e0..05c112bfc8 100644 --- a/src/pmc/class.pmc +++ b/src/pmc/class.pmc @@ -1421,7 +1421,7 @@ Returns the integer type of the class. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the class. @@ -1431,7 +1431,7 @@ C<*info> is the visit info, (see F). */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { /* 1) visit the attribute description hash */ VISIT_PMC_ATTR(INTERP, info, SELF, Class, attrib_metadata); @@ -1453,7 +1453,7 @@ C<*info> is the visit info, (see F). /* -=item C +=item C Used to archive the class. @@ -1461,7 +1461,7 @@ Used to archive the class. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { Parrot_Class_attributes * const class_data = PARROT_CLASS(SELF); STRING *serial_namespace = CONST_STRING(interp, ""); @@ -1483,7 +1483,7 @@ Used to archive the class. /* -=item C +=item C Used to unarchive the class. @@ -1491,7 +1491,7 @@ Used to unarchive the class. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { /* The class might already exist in the interpreter, so create it as an * anonymous class and later decide whether to link it into the * namespace. */ @@ -1549,7 +1549,7 @@ with functions like pmc_new and pmc_reuse, which take type ID numbers still. /* -=item C +=item C Called after the class has been thawed. @@ -1557,7 +1557,7 @@ Called after the class has been thawed. */ - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { Parrot_Class_attributes * const _class = PARROT_CLASS(SELF); UNUSED(info) diff --git a/src/pmc/default.pmc b/src/pmc/default.pmc index 4ffc802728..7d52cf2b8f 100644 --- a/src/pmc/default.pmc +++ b/src/pmc/default.pmc @@ -1043,7 +1043,7 @@ Add class C to the list of our parents. /* -=item C +=item C Used by GC to mark the PMC. @@ -1051,7 +1051,7 @@ Used by GC to mark the PMC. */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { } /* @@ -1070,7 +1070,7 @@ Clones this PMC. By default, this just does a freeze and thaw. /* -=item C +=item C Does nothing. @@ -1078,14 +1078,14 @@ Does nothing. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { UNUSED(info) /* default - no action */ } /* -=item C +=item C Initializes the PMC during unarchiving. @@ -1093,14 +1093,14 @@ Initializes the PMC during unarchiving. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { /* default - initialize the PMC */ SELF.init(); } /* -=item C +=item C Does nothing. @@ -1108,7 +1108,7 @@ Does nothing. */ - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { UNUSED(info) /* default - no action */ } diff --git a/src/pmc/eval.pmc b/src/pmc/eval.pmc index 0dba718a72..cee2480a1a 100644 --- a/src/pmc/eval.pmc +++ b/src/pmc/eval.pmc @@ -320,11 +320,11 @@ Returns the Sub PMC of the element at index C or PMCNULL. /* -=item C +=item C Archives the evaled code -=item C +=item C Unarchives the code. @@ -332,14 +332,14 @@ Unarchives the code. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { STRING *packed = SELF.get_string(); VTABLE_push_string(INTERP, info, packed); SUPER(info); } - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { STRING *packed = VTABLE_shift_string(INTERP, info); PackFile *pf; PackFile_Segment *seg; diff --git a/src/pmc/fixedbooleanarray.pmc b/src/pmc/fixedbooleanarray.pmc index e1a08e478f..9b9d150cb9 100644 --- a/src/pmc/fixedbooleanarray.pmc +++ b/src/pmc/fixedbooleanarray.pmc @@ -506,14 +506,14 @@ Return a new iterator for SELF. =over 4 -=item C +=item C Used to archive the string. =cut */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { UINTVAL size, resize_threshold; unsigned char * bit_array; STRING * s; @@ -530,14 +530,14 @@ Used to archive the string. /* -=item C +=item C Used to unarchive the string. =cut */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { SUPER(info); { diff --git a/src/pmc/fixedintegerarray.pmc b/src/pmc/fixedintegerarray.pmc index 93203f6795..4ab7e70b7f 100644 --- a/src/pmc/fixedintegerarray.pmc +++ b/src/pmc/fixedintegerarray.pmc @@ -537,17 +537,17 @@ Return a new Iterator for this PMC. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the array. C<*info> is the visit info, (see F). -=item C +=item C Used to archive the array. -=item C +=item C Used to unarchive the array. @@ -555,11 +555,11 @@ Used to unarchive the array. */ - /*VTABLE void visit(visit_info *info) { + /*VTABLE void visit(PMC *info) { SUPER(info); }*/ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { INTVAL *int_array; INTVAL i, n; @@ -573,7 +573,7 @@ Used to unarchive the array. VTABLE_push_integer(INTERP, info, int_array[i]); } - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { INTVAL n; SUPER(info); diff --git a/src/pmc/fixedpmcarray.pmc b/src/pmc/fixedpmcarray.pmc index 1fa362d62e..ae98ebeabb 100644 --- a/src/pmc/fixedpmcarray.pmc +++ b/src/pmc/fixedpmcarray.pmc @@ -690,17 +690,17 @@ of this array. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the array. C<*info> is the visit info, (see F). -=item C +=item C Used to archive the array. -=item C +=item C Used to unarchive the array. @@ -708,25 +708,24 @@ Used to unarchive the array. */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { INTVAL i; const INTVAL n = VTABLE_elements(INTERP, SELF); PMC **pos = PMC_array(SELF); for (i = 0; i < n; ++i, ++pos) { - info->thaw_ptr = pos; - (info->visit_pmc_now)(INTERP, *pos, info); + VISIT_PMC(INTERP, info, *pos); } SUPER(info); } - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { SUPER(info); VTABLE_push_integer(INTERP, info, VTABLE_elements(INTERP, SELF)); } - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { SUPER(info); SELF.set_integer_native(VTABLE_shift_integer(INTERP, info)); } diff --git a/src/pmc/fixedstringarray.pmc b/src/pmc/fixedstringarray.pmc index 31d0c3346b..50c1cc0057 100644 --- a/src/pmc/fixedstringarray.pmc +++ b/src/pmc/fixedstringarray.pmc @@ -559,14 +559,14 @@ The C<==> operation. Compares two array to hold equal elements. =over 4 -=item C +=item C Used to archive the string. =cut */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { STRING **str_array; UINTVAL size, i; @@ -580,14 +580,14 @@ Used to archive the string. /* -=item C +=item C Used to unarchive the string. =cut */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { UINTVAL i, size; STRING **str_array; diff --git a/src/pmc/float.pmc b/src/pmc/float.pmc index 250324d8e1..9b1ff6c957 100644 --- a/src/pmc/float.pmc +++ b/src/pmc/float.pmc @@ -344,28 +344,28 @@ Sets C to the absolute value of SELF. /* -=item C +=item C Used to archive the number. =cut */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { SUPER(info); VTABLE_push_float(INTERP, info, SELF.get_number()); } /* -=item C +=item C Used to unarchive the number. =cut */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { SUPER(info); SET_ATTR_fv(INTERP, SELF, VTABLE_shift_float(INTERP, info)); } diff --git a/src/pmc/hash.pmc b/src/pmc/hash.pmc index b40520be9e..02c1d7d2a6 100644 --- a/src/pmc/hash.pmc +++ b/src/pmc/hash.pmc @@ -1078,7 +1078,7 @@ Return a new iterator for the slice PMC C /* -=item C +=item C Used during archiving to visit the elements in the hash. @@ -1086,14 +1086,14 @@ Used during archiving to visit the elements in the hash. */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { parrot_hash_visit(INTERP, (Hash *)SELF.get_pointer(), info); SUPER(info); } /* -=item C +=item C Used to archive the hash. @@ -1101,7 +1101,7 @@ Used to archive the hash. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { Hash * const hash = (Hash *)SELF.get_pointer();; SUPER(info); @@ -1112,7 +1112,7 @@ Used to archive the hash. /* -=item C +=item C Used to unarchive the hash. @@ -1120,7 +1120,7 @@ Used to unarchive the hash. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { SUPER(info); { diff --git a/src/pmc/imageio.pmc b/src/pmc/imageio.pmc new file mode 100644 index 0000000000..d920579521 --- /dev/null +++ b/src/pmc/imageio.pmc @@ -0,0 +1,590 @@ +/* +Copyright (C) 2010, Parrot Foundation. +$Id$ + +=head1 NAME + +src/pmc/imageio.pmc - ImageIO PMC + +=head1 DESCRIPTION + +Freezes and thaws other PMCs. + +*/ + +#define GROW_TO_16_BYTE_BOUNDARY(size) ((size) + ((size) % 16 ? 16 - (size) % 16 : 0)) + +/* when thawing a string longer then this size, we first do a GC run and then + * block GC - the system can't give us more headers */ + +#define THAW_BLOCK_GC_SIZE 100000 + +/* preallocate freeze image for aggregates with this estimation */ +#define FREEZE_BYTES_PER_ITEM 9 + +/* macros/constants to handle packing/unpacking of PMC IDs and flags + * the 2 LSBs are used for flags, all other bits are used for PMC ID + */ +#define PackID_new(id, flags) (((UINTVAL)(id) * 4) | ((UINTVAL)(flags) & 3)) +#define PackID_get_PMCID(id) ((UINTVAL)(id) / 4) +#define PackID_set_PMCID(lv, id) (lv) = PackID_new((id), PackID_get_FLAGS(lv)) +#define PackID_get_FLAGS(id) ((UINTVAL)(id) & 3) +#define PackID_set_FLAGS(lv, flags) (lv) = PackID_new(PackID_get_PMCID(lv), (flags)) + +enum { + enum_PackID_normal = 0, + enum_PackID_seen = 1, +}; + +PARROT_INLINE +static opcode_t * +GET_VISIT_CURSOR(PMC *pmc){ + char *buf = (char *)Buffer_bufstart(PARROT_IMAGEIO(pmc)->buffer); + size_t pos = PARROT_IMAGEIO(pmc)->pos; + return (opcode_t *)(buf + pos); +} + +PARROT_INLINE +static void +SET_VISIT_CURSOR(PMC *pmc, char *cursor) { + char *bufstart = (char *)Buffer_bufstart(PARROT_IMAGEIO(pmc)->buffer); + PARROT_IMAGEIO(pmc)->pos = (cursor - bufstart); +} + +PARROT_INLINE +static void +INC_VISIT_CURSOR(PMC *pmc, UINTVAL inc) { + PARROT_IMAGEIO(pmc)->pos += inc; +} + +#define BYTECODE_SHIFT_OK(pmc) PARROT_ASSERT( \ + PARROT_IMAGEIO(pmc)->pos <= PARROT_IMAGEIO(pmc)->input_length) + + + +static void +create_buffer(PARROT_INTERP, PMC *pmc, PMC *info) +{ + INTVAL len; + + if (!PMC_IS_NULL(pmc)) { + STRING *array = CONST_STRING(interp, "array"); + STRING *hash = CONST_STRING(interp, "hash"); + INTVAL items = 1; + + if (VTABLE_does(interp, pmc, array) || VTABLE_does(interp, pmc, hash)) { + items += VTABLE_elements(interp, pmc); + } + len = items * FREEZE_BYTES_PER_ITEM; + } + else + len = FREEZE_BYTES_PER_ITEM; + + PARROT_IMAGEIO(info)->buffer = + (Buffer *)Parrot_gc_new_bufferlike_header(interp, sizeof (Buffer)); + Parrot_gc_allocate_buffer_storage_aligned(interp, + PARROT_IMAGEIO(info)->buffer, len); + SET_VISIT_CURSOR(info, (char *)Buffer_bufstart(PARROT_IMAGEIO(info)->buffer)); +} + + +/* +static void ensure_buffer_size(PARROT_INTERP, PMC *io, size_t len) + +Checks the size of the buffer to see if it can accommodate 'len' more +bytes. If not, expands the buffer. + +*/ + +PARROT_INLINE +static void +ensure_buffer_size(PARROT_INTERP, ARGIN(PMC *io), size_t len) +{ + Buffer *buf = PARROT_IMAGEIO(io)->buffer; + const size_t used = PARROT_IMAGEIO(io)->pos; + const int need_free = Buffer_buflen(buf) - used - len; + + /* grow by factor 1.5 or such */ + if (need_free <= 16) { + size_t new_size = (size_t) (Buffer_buflen(buf) * 1.5); + if (new_size < Buffer_buflen(buf) - need_free + 512) + new_size = Buffer_buflen(buf) - need_free + 512; + Parrot_gc_reallocate_buffer_storage(interp, buf, new_size); + PARROT_ASSERT(Buffer_buflen(buf) - used - len >= 15); + } + +#ifndef DISABLE_GC_DEBUG + Parrot_gc_compact_memory_pool(INTERP); +#endif + +} + +PARROT_INLINE +static INTVAL +INFO_HAS_DATA(ARGIN(PMC *io)) { + return PARROT_IMAGEIO(io)->pos < PARROT_IMAGEIO(io)->input_length; +} + +PARROT_INLINE +static PMC* +id_list_get(PARROT_INTERP, PMC *io, UINTVAL id) { + return VTABLE_get_pmc_keyed_int(interp, PARROT_IMAGEIO(io)->id_list, id); +} + +PARROT_INLINE +static void +visit_todo_list_thaw(PARROT_INTERP, SHIM(PMC* pmc_not_used), ARGIN(PMC* info)) +{ + UINTVAL n = VTABLE_shift_integer(interp, info); + UINTVAL id = PackID_get_PMCID(n); + int packid_flags = PackID_get_FLAGS(n); + PMC *pmc = PMCNULL; + + PARROT_ASSERT(PARROT_IMAGEIO(info)->what == VISIT_THAW_NORMAL); + + switch (packid_flags) { + case enum_PackID_seen: + if (id) /* got a non-NULL PMC */ + pmc = id_list_get(interp, info, id); + break; + case enum_PackID_normal: + { + INTVAL type = VTABLE_shift_integer(interp, info); + if (type <= 0 || type > interp->n_vtable_max) + Parrot_ex_throw_from_c_args(interp, NULL, 1, "Unknown PMC type to thaw %d", type); + + pmc = pmc_new_noinit(interp, type); + VTABLE_thaw(interp, pmc, info); + + { + PMC * const todo = PARROT_IMAGEIO(info)->todo; + PMC * const id_list = PARROT_IMAGEIO(info)->id_list; + VTABLE_set_pmc_keyed_int(interp, id_list, id, pmc); + /* remember nested aggregates depth first */ + VTABLE_unshift_pmc(interp, todo, pmc); + } + } + break; + default: + Parrot_ex_throw_from_c_args(interp, NULL, 1, "Unknown PMC id args thaw %d", packid_flags); + break; + } + + *(PARROT_IMAGEIO(info)->thaw_ptr) = pmc; +} + +static void +visit_todo_list_freeze(PARROT_INTERP, PMC* pmc, PMC* info) +{ + UINTVAL id; + int packid_type; + + PARROT_ASSERT(PARROT_IMAGEIO(info)->what == VISIT_FREEZE_NORMAL); + + if (PMC_IS_NULL(pmc)) { + id = 0; + packid_type = enum_PackID_seen; + } + else { + Hash *hash = (Hash *)VTABLE_get_pointer(interp, PARROT_IMAGEIO(info)->seen); + HashBucket * const b = parrot_hash_get_bucket(interp, hash, pmc); + if (b) { + id = (UINTVAL) b->value; + packid_type = enum_PackID_seen; + } + else { + PARROT_IMAGEIO(info)->id++; /* next id to freeze */ + id = PARROT_IMAGEIO(info)->id; + packid_type = enum_PackID_normal; + } + } + + VTABLE_push_integer(interp, info, PackID_new(id, packid_type)); + + if (packid_type == enum_PackID_normal) { + Hash *hash = (Hash *)VTABLE_get_pointer(interp, PARROT_IMAGEIO(info)->seen); + PARROT_ASSERT(pmc); + VTABLE_push_integer(interp, info, + PObj_is_object_TEST(pmc) ? enum_class_Object : pmc->vtable->base_type); + parrot_hash_put(interp, hash, pmc, (void *)id); + VTABLE_unshift_pmc(interp, PARROT_IMAGEIO(info)->todo, pmc); + VTABLE_freeze(interp, pmc, info); + } +} + +static void +visit_loop_todo_list(PARROT_INTERP, PMC *current, PMC *info) +{ + PMC * const todo = PARROT_IMAGEIO(info)->todo; + const int thawing = PARROT_IMAGEIO(info)->what == VISIT_THAW_NORMAL; + + (PARROT_IMAGEIO(info)->visit_pmc_now)(interp, current, info); + + /* can't cache upper limit, visit may append items */ + while (VTABLE_get_bool(interp, todo)) { + current = VTABLE_shift_pmc(interp, todo); + if (!current) + Parrot_ex_throw_from_c_args(interp, NULL, 1, + "NULL current PMC in visit_loop_todo_list"); + + PARROT_ASSERT(current->vtable); + + VTABLE_visit(interp, current, info); + + VISIT_PMC(interp, info, PMC_metadata(current)); + } + + if (thawing) + /* we're done reading the image */ + PARROT_ASSERT(!INFO_HAS_DATA(info)); + + if (thawing) { + /* on thawing call thawfinish for each processed PMC */ + const INTVAL n = VTABLE_elements(interp, PARROT_IMAGEIO(info)->id_list); + int i; + + /* + * Thaw in reverse order. We have to fully thaw younger PMCs + * before use them in older. + * + * XXX There are no younger or older pmcs in a directed graph + * that allows cycles. Any code that requires a specific + * order here is likely broken. + */ + for (i = n-1; i >= 0; --i) { + current = VTABLE_get_pmc_keyed_int(interp, PARROT_IMAGEIO(info)->id_list, i); + if (!PMC_IS_NULL(current)) + VTABLE_thawfinish(interp, current, info); + } + } +} + +pmclass ImageIO auto_attrs { + ATTR visit_f visit_pmc_now; + ATTR Buffer *buffer; /* buffer to store the image */ + ATTR size_t pos; /* current read/write position in buffer */ + ATTR size_t input_length; + ATTR INTVAL what; + ATTR PMC **thaw_ptr; /* where to thaw a new PMC */ + ATTR PMC *seen; /* seen hash */ + ATTR PMC *todo; /* todo list */ + ATTR PMC *id_list; /* seen list used by thaw */ + ATTR UINTVAL id; /* freze ID of PMC */ + ATTR INTVAL extra_flags; /* concerning to extra */ + ATTR struct PackFile *pf; + +/* + +=head1 VTABLES + +=over 4 + +=cut + +*/ + +/* + +=item C + +Initializes the PMC. + +=cut + +*/ + VTABLE void init() { + PARROT_IMAGEIO(SELF)->thaw_ptr = NULL; + PARROT_IMAGEIO(SELF)->buffer = NULL; + PARROT_IMAGEIO(SELF)->todo = pmc_new(INTERP, enum_class_ResizablePMCArray); + PARROT_IMAGEIO(SELF)->seen = PMCNULL; + PARROT_IMAGEIO(SELF)->id_list = PMCNULL; + PARROT_IMAGEIO(SELF)->id = 0; + PARROT_IMAGEIO(SELF)->extra_flags = EXTRA_IS_NULL; + PARROT_IMAGEIO(SELF)->pf = PackFile_new(INTERP, 0); + + PObj_custom_mark_destroy_SETALL(SELF); + } + + +/* + +=item C + +Destroys the PMC. + +=cut + +*/ + VTABLE void destroy() { + PackFile_destroy(INTERP, PARROT_IMAGEIO(SELF)->pf); + } + +/* + +=item C + +Marks the PMC as alive. + +=cut + +*/ + VTABLE void mark() { + Parrot_gc_mark_PObj_alive(INTERP, (PObj *)(PARROT_IMAGEIO(SELF)->buffer)); + Parrot_gc_mark_PMC_alive(INTERP, PARROT_IMAGEIO(SELF)->todo); + Parrot_gc_mark_PMC_alive(INTERP, PARROT_IMAGEIO(SELF)->seen); + Parrot_gc_mark_PMC_alive(INTERP, PARROT_IMAGEIO(SELF)->id_list); + } + +/* + +=item C + +Returns the content of the image as a string. + +=cut + +*/ + + VTABLE STRING *get_string() { + return Parrot_str_new_from_buffer(INTERP, + PARROT_IMAGEIO(SELF)->buffer, + PARROT_IMAGEIO(SELF)->pos); + } +/* + +/* + +=item C + +Sets the location where to thaw a new PMC. + +=cut + +*/ + +VTABLE void set_pointer(void* value) { + PARROT_IMAGEIO(SELF)->thaw_ptr = value; +} + +/* + +=item C + +Returns the flags describing the visit action + +=cut + +*/ + +VTABLE INTVAL get_integer() { + return PARROT_IMAGEIO(SELF)->what; +} + +/* + +=item C + +Pushes the integer C onto the end of the image. + +=cut + +*/ + +VTABLE void push_integer(INTVAL v) { + size_t len = PF_size_integer() * sizeof (opcode_t); + ensure_buffer_size(interp, SELF, len); + SET_VISIT_CURSOR(SELF, (char *)PF_store_integer(GET_VISIT_CURSOR(SELF), v)); +} + + +/* + +=item C + +Pushes the float C onto the end of the image. + +=cut + +*/ + +VTABLE void push_float(FLOATVAL v) +{ + size_t len = PF_size_number() * sizeof (opcode_t); + ensure_buffer_size(interp, SELF, len); + SET_VISIT_CURSOR(SELF, (char *)PF_store_number(GET_VISIT_CURSOR(SELF), &v)); +} + + +/* + +=item C + +Pushes the string C<*v> onto the end of the image. + +=cut + +*/ + +VTABLE void push_string(STRING *v) +{ + size_t len = PF_size_string(v) * sizeof (opcode_t); + ensure_buffer_size(INTERP, SELF, len); + SET_VISIT_CURSOR(SELF, (char *)PF_store_string(GET_VISIT_CURSOR(SELF), v)); +} + +/* + +=item C + +Pushes a reference to pmc C<*v> onto the end of the image. If C<*v> +hasn't been seen yet, it is also pushed onto the todo list. + +=cut + +*/ + +VTABLE void push_pmc(PMC *v) { + VTABLE_set_pointer(interp, SELF, &v); + (PARROT_IMAGEIO(SELF)->visit_pmc_now)(INTERP, v, SELF); +} + +/* + +=item C + +Removes and returns an integer from the start of the image. + +=cut + +*/ + +VTABLE INTVAL shift_integer() +{ + opcode_t *pos = GET_VISIT_CURSOR(SELF); + const INTVAL i = PF_fetch_integer(PARROT_IMAGEIO(SELF)->pf, (const opcode_t **)&pos); + SET_VISIT_CURSOR(SELF, (char *)pos); + BYTECODE_SHIFT_OK(SELF); + return i; +} + + +/* + +=item C + +Removes and returns an number from the start of the image. + +=cut + +*/ + +VTABLE FLOATVAL shift_float() { + opcode_t *pos = GET_VISIT_CURSOR(SELF); + const FLOATVAL f = PF_fetch_number(PARROT_IMAGEIO(SELF)->pf, (const opcode_t **)&pos); + SET_VISIT_CURSOR(SELF, (char *)pos); + BYTECODE_SHIFT_OK(SELF); + return f; +} + + +/* + +=item C + +Removes and returns a string from the start of the image. + +=cut + +*/ + +VTABLE STRING *shift_string() +{ + opcode_t *pos = GET_VISIT_CURSOR(SELF); + STRING * const s = PF_fetch_string(interp, PARROT_IMAGEIO(SELF)->pf, (const opcode_t **)&pos); + SET_VISIT_CURSOR(SELF, (char *)pos); + BYTECODE_SHIFT_OK(SELF); + return s; +} + +/* + +=item C + +Removes and returns a reference to a pmc from the start of the image. + +=cut + +*/ + +VTABLE PMC *shift_pmc() { + PMC *result; + VTABLE_set_pointer(interp, SELF, &result); + (PARROT_IMAGEIO(SELF)->visit_pmc_now)(interp, NULL, SELF); + return result; +} + +VTABLE void set_pmc(PMC *p) +{ + UINTVAL header_length = GROW_TO_16_BYTE_BOUNDARY(PACKFILE_HEADER_BYTES); + + PARROT_IMAGEIO(SELF)->what = VISIT_FREEZE_NORMAL; + PARROT_IMAGEIO(SELF)->visit_pmc_now = visit_todo_list_freeze; + create_buffer(INTERP, p, SELF); + ensure_buffer_size(INTERP, SELF, header_length); + mem_sys_memcopy(GET_VISIT_CURSOR(SELF), + PARROT_IMAGEIO(SELF)->pf->header, PACKFILE_HEADER_BYTES); + INC_VISIT_CURSOR(SELF, header_length); + + PARROT_IMAGEIO(SELF)->seen = pmc_new(INTERP, enum_class_Hash); + VTABLE_set_pointer(INTERP, PARROT_IMAGEIO(SELF)->seen, + parrot_new_intval_hash(INTERP)); + + visit_loop_todo_list(INTERP, p, SELF); +} + +VTABLE void set_string_native(STRING *image) { + UINTVAL header_length = GROW_TO_16_BYTE_BOUNDARY(PACKFILE_HEADER_BYTES); + int unpacked_length; + + PARROT_IMAGEIO(SELF)->what = VISIT_THAW_NORMAL; + PARROT_IMAGEIO(SELF)->visit_pmc_now = visit_todo_list_thaw; + PARROT_IMAGEIO(SELF)->buffer = (Buffer *)image; + PARROT_IMAGEIO(SELF)->id_list = pmc_new(INTERP, enum_class_ResizablePMCArray); + + PARROT_ASSERT(image->_bufstart == image->strstart); + + SET_VISIT_CURSOR(SELF, (char *)Buffer_bufstart(PARROT_IMAGEIO(SELF)->buffer)); + PARROT_IMAGEIO(SELF)->input_length = image->strlen; + + PARROT_IMAGEIO(SELF)->pf->options |= PFOPT_PMC_FREEZE_ONLY; + unpacked_length = PackFile_unpack(interp, PARROT_IMAGEIO(SELF)->pf, + GET_VISIT_CURSOR(SELF), PARROT_IMAGEIO(SELF)->input_length); + + if (!unpacked_length) { + Parrot_ex_throw_from_c_args(interp, NULL, + EXCEPTION_INVALID_STRING_REPRESENTATION, + "PackFile header failed during unpack"); + } + else { + INC_VISIT_CURSOR(SELF, header_length); + } + + visit_loop_todo_list(interp, pmc, SELF); +} + +/* + +=back + +=cut + +*/ + +} + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4: + */ diff --git a/src/pmc/integer.pmc b/src/pmc/integer.pmc index 1e2a374d21..1f3c7e08ea 100644 --- a/src/pmc/integer.pmc +++ b/src/pmc/integer.pmc @@ -1304,14 +1304,14 @@ and 36, inclusive. /* -=item C +=item C Used to archive the integer. =cut */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { SUPER(info); VTABLE_push_integer(INTERP, info, SELF.get_integer()); } @@ -1319,14 +1319,14 @@ Used to archive the integer. /* -=item C +=item C Used to unarchive the integer. =cut */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { SUPER(info); SELF.set_integer_native(VTABLE_shift_integer(INTERP, info)); } diff --git a/src/pmc/key.pmc b/src/pmc/key.pmc index 9ccd46bcac..68b4fbb09f 100644 --- a/src/pmc/key.pmc +++ b/src/pmc/key.pmc @@ -283,19 +283,19 @@ Returns the key itself. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the Key. -=item C +=item C Archives the Key. -=item C +=item C Unarchives the Key. -=item C +=item C Called after the Key has been thawed: convert last PMC_NULL key to NULL. @@ -303,7 +303,7 @@ Called after the Key has been thawed: convert last PMC_NULL key to NULL. */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { /* Sometimes visit gets an uninitialized Key. Initialize it. */ if (!PMC_data(SELF)) SELF.init(); @@ -311,7 +311,7 @@ Called after the Key has been thawed: convert last PMC_NULL key to NULL. VISIT_PMC_ATTR(INTERP, info, SELF, Key, next_key); } - void freeze(visit_info *info) { + void freeze(PMC *info) { /* write flags */ const INTVAL flags = (PObj_get_FLAGS(SELF) & KEY_type_FLAGS); @@ -340,7 +340,7 @@ Called after the Key has been thawed: convert last PMC_NULL key to NULL. } } - void thaw(visit_info *info) { + void thaw(PMC *info) { const INTVAL flags = VTABLE_shift_integer(INTERP, info) & KEY_type_FLAGS; PObj_get_FLAGS(SELF) |= flags; @@ -367,7 +367,7 @@ Called after the Key has been thawed: convert last PMC_NULL key to NULL. } } - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { PMC *key = SELF; UNUSED(info) diff --git a/src/pmc/lexinfo.pmc b/src/pmc/lexinfo.pmc index 06966e5284..4179f24e0f 100644 --- a/src/pmc/lexinfo.pmc +++ b/src/pmc/lexinfo.pmc @@ -125,11 +125,11 @@ C, which gets an array of the names of the symbols in this lexpad. /* -=item C +=item C -=item C +=item C -=item C +=item C Freeze/thaw interface used during freeze/thaw of the Sub PMC. The implementation of the Hash PMC is called. @@ -139,7 +139,7 @@ The implementation of the Hash PMC is called. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { const INTVAL elems = VTABLE_shift_integer(INTERP, info); const INTVAL k_type = VTABLE_shift_integer(INTERP, info); const INTVAL v_type = VTABLE_shift_integer(INTERP, info); diff --git a/src/pmc/object.pmc b/src/pmc/object.pmc index 13972a1551..909edef167 100644 --- a/src/pmc/object.pmc +++ b/src/pmc/object.pmc @@ -725,7 +725,7 @@ Creates a clone of the object. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the object. @@ -735,24 +735,19 @@ C<*info> is the visit info, (see F). */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { Parrot_Object_attributes * const obj_data = PARROT_OBJECT(SELF); - PMC **pos; /* 1) visit class */ - pos = &obj_data->_class; - info->thaw_ptr = pos; - (info->visit_pmc_now)(INTERP, *pos, info); + VISIT_PMC(INTERP, info, obj_data->_class); /* 2) visit the attributes */ - pos = &obj_data->attrib_store; - info->thaw_ptr = pos; - (info->visit_pmc_now)(INTERP, *pos, info); + VISIT_PMC(INTERP, info, obj_data->attrib_store); } /* -=item C +=item C Used to unarchive the object. @@ -760,13 +755,13 @@ Used to unarchive the object. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { return; } /* -=item C +=item C Called after the object has been thawed. @@ -774,7 +769,7 @@ Called after the object has been thawed. */ - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { /* Set custom GC mark and destroy on the object. */ PObj_custom_mark_SET(SELF); PObj_custom_destroy_SET(SELF); diff --git a/src/pmc/orderedhash.pmc b/src/pmc/orderedhash.pmc index 681366425a..147e3ad00a 100644 --- a/src/pmc/orderedhash.pmc +++ b/src/pmc/orderedhash.pmc @@ -726,15 +726,15 @@ the clone via integers has different indices, if items were deleted. } /* -=item C +=item C Used during archiving to visit the elements in the hash. -=item C +=item C Used to archive the hash. -=item C +=item C Used to unarchive the hash. @@ -742,12 +742,12 @@ Used to unarchive the hash. */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { VISIT_PMC_ATTR(INTERP, info, SELF, OrderedHash, hash); SUPER(info); } - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { Parrot_OrderedHash_attributes *attrs = PARROT_ORDEREDHASH(SELF); find_bounds(INTERP, attrs->hash, &attrs->first, &attrs->last); SUPER(info); diff --git a/src/pmc/parrotinterpreter.pmc b/src/pmc/parrotinterpreter.pmc index e99f6c4259..34e07f0c0d 100644 --- a/src/pmc/parrotinterpreter.pmc +++ b/src/pmc/parrotinterpreter.pmc @@ -658,24 +658,24 @@ have the same thread id. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the interpreter. C<*info> is the visit info, (see F). -=item C +=item C Used to archive the interpreter. Actually not the whole interpreter is frozen but the state of the interpreter, which includes everything that has changes since creating an empty interpreter. -=item C +=item C Used to unarchive the interpreter. This merges the changes into this interpreter instance. -=item C +=item C Finish thawing. @@ -683,8 +683,7 @@ Finish thawing. */ - VTABLE void visit(visit_info *info) { - PMC **pos; + VTABLE void visit(PMC *info) { /* * the information frozen here is part of all PBCs * we probably need to freeze all dynamic extensible @@ -710,16 +709,14 @@ Finish thawing. /* HLL_info */ if (VTABLE_get_integer(INTERP, info) == VISIT_THAW_NORMAL || VTABLE_get_integer(INTERP, info) == VISIT_THAW_CONSTANTS) { - pos = &PMC_args(SELF); + VISIT_PMC(interp, info, PMC_args(SELF)); } else - pos = &INTERP->HLL_info; + VISIT_PMC(interp, info, INTERP->HLL_info); - info->thaw_ptr = pos; - (info->visit_pmc_now)(INTERP, *pos, info); } - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { if (!PMC_data(SELF)) { Parrot_ParrotInterpreter_attributes *attrs = mem_allocate_zeroed_typed(Parrot_ParrotInterpreter_attributes); @@ -730,7 +727,7 @@ Finish thawing. PMC_interp(SELF) = INTERP; } - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { PMC * const new_info = PMC_args(SELF); const INTVAL m = VTABLE_elements(INTERP, new_info); INTVAL i; @@ -845,5 +842,3 @@ This method is experimental. See TT #264. * End: * vim: expandtab shiftwidth=4: */ - - diff --git a/src/pmc/resizablebooleanarray.pmc b/src/pmc/resizablebooleanarray.pmc index 69a653c526..3b1fc2a7b1 100644 --- a/src/pmc/resizablebooleanarray.pmc +++ b/src/pmc/resizablebooleanarray.pmc @@ -404,14 +404,14 @@ Returns a copy of the array. =over 4 -=item C +=item C Used to archive the string. =cut */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { /* XXX Dino - I'm concerned about freezing the entire allocated block of memory, it's dependent on the BITS_PER_CHAR value. @@ -438,14 +438,14 @@ Used to archive the string. /* -=item C +=item C Used to unarchive the string. =cut */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { unsigned char *bit_array; const UINTVAL head_pos = VTABLE_shift_integer(INTERP, info); const UINTVAL tail_pos = VTABLE_shift_integer(INTERP, info); diff --git a/src/pmc/resizableintegerarray.pmc b/src/pmc/resizableintegerarray.pmc index be700a1a9e..02c272b462 100644 --- a/src/pmc/resizableintegerarray.pmc +++ b/src/pmc/resizableintegerarray.pmc @@ -279,11 +279,11 @@ Creates and returns a copy of the array. /* -=item C +=item C Used to archive the array. -=item C +=item C Used to unarchive the array. @@ -291,7 +291,7 @@ Used to unarchive the array. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { INTVAL *int_array; INTVAL i, n, rt; @@ -308,7 +308,7 @@ Used to unarchive the array. VTABLE_push_integer(INTERP, info, int_array[i]); } - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { const INTVAL n = VTABLE_shift_integer(INTERP, info); const INTVAL rt = VTABLE_shift_integer(INTERP, info); diff --git a/src/pmc/scheduler.pmc b/src/pmc/scheduler.pmc index c21555607d..7e5c0b6cee 100644 --- a/src/pmc/scheduler.pmc +++ b/src/pmc/scheduler.pmc @@ -277,7 +277,7 @@ Marks any referenced strings and PMCs as live. /* -=item C +=item C Visits the contents of the scheduler (used by freeze/thaw). @@ -287,7 +287,7 @@ C<*info> is the visit info (see F). */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { /* 1) visit task list */ VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, task_list); @@ -298,7 +298,7 @@ C<*info> is the visit info (see F). /* -=item C +=item C Archives the scheduler. @@ -306,7 +306,7 @@ Archives the scheduler. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF); /* 1) freeze scheduler id */ @@ -319,7 +319,7 @@ Archives the scheduler. /* -=item C +=item C Unarchives the scheduler. @@ -327,7 +327,7 @@ Unarchives the scheduler. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { /* 1. thaw scheduler id */ const INTVAL id = VTABLE_shift_integer(INTERP, info); @@ -347,7 +347,7 @@ Unarchives the scheduler. /* -=item C +=item C Finishes thawing the scheduler. @@ -355,7 +355,7 @@ Finishes thawing the scheduler. */ - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { Parrot_cx_refresh_task_list(INTERP, SELF); } diff --git a/src/pmc/schedulermessage.pmc b/src/pmc/schedulermessage.pmc index 81f80551e7..b6b6c322ac 100644 --- a/src/pmc/schedulermessage.pmc +++ b/src/pmc/schedulermessage.pmc @@ -206,7 +206,7 @@ Mark any referenced strings and PMCs. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the scheduler message. @@ -216,20 +216,14 @@ C<*info> is the visit info, (see F). */ - VTABLE void visit(visit_info *info) { - Parrot_SchedulerMessage_attributes * const core_struct = - PARROT_SCHEDULERMESSAGE(SELF); - PMC **pos; - - /* 1) visit message data */ - pos = &core_struct->data; - info->thaw_ptr = pos; - (info->visit_pmc_now)(INTERP, *pos, info); + VTABLE void visit(PMC *info) { + /* visit message data */ + VISIT_PMC(INTERP, info, PARROT_SCHEDULERMESSAGE(SELF)->data); } /* -=item C +=item C Used to archive the scheduler message. @@ -237,7 +231,7 @@ Used to archive the scheduler message. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { Parrot_SchedulerMessage_attributes * const core_struct = PARROT_SCHEDULERMESSAGE(SELF); @@ -250,7 +244,7 @@ Used to archive the scheduler message. /* -=item C +=item C Used to unarchive the scheduler message. @@ -258,7 +252,7 @@ Used to unarchive the scheduler message. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { /* 1. thaw message id */ const INTVAL id = VTABLE_shift_integer(INTERP, info); diff --git a/src/pmc/string.pmc b/src/pmc/string.pmc index c73178dd37..82a62e9b2c 100644 --- a/src/pmc/string.pmc +++ b/src/pmc/string.pmc @@ -778,28 +778,28 @@ Return length of the string. =over 4 -=item C +=item C Used to archive the string. =cut */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { SUPER(info); VTABLE_push_string(INTERP, info, VTABLE_get_string(INTERP, SELF)); } /* -=item C +=item C Used to unarchive the string. =cut */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { SUPER(info); SET_ATTR_str_val(INTERP, SELF, VTABLE_shift_string(INTERP, info)); } diff --git a/src/pmc/sub.pmc b/src/pmc/sub.pmc index d546a73d48..bc5d0ac72c 100644 --- a/src/pmc/sub.pmc +++ b/src/pmc/sub.pmc @@ -619,11 +619,11 @@ Returns whether the two subroutines are equal. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the sub. -=item C +=item C Archives the subroutine. @@ -631,7 +631,7 @@ Archives the subroutine. */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { VISIT_PMC_ATTR(INTERP, info, SELF, Sub, namespace_name); VISIT_PMC_ATTR(INTERP, info, SELF, Sub, multi_signature); @@ -651,7 +651,7 @@ Archives the subroutine. SUPER(info); } - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { Parrot_Sub_attributes *sub; STRING *hll_name; int i; @@ -709,7 +709,7 @@ Archives the subroutine. /* -=item C +=item C Unarchives the subroutine. @@ -717,7 +717,7 @@ Unarchives the subroutine. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { Parrot_Sub_attributes *sub; INTVAL flags; int i; diff --git a/src/pmc/task.pmc b/src/pmc/task.pmc index beb785d03e..96ca765f36 100644 --- a/src/pmc/task.pmc +++ b/src/pmc/task.pmc @@ -385,7 +385,7 @@ Mark any referenced strings and PMCs. /* -=item C +=item C This is used by freeze/thaw to visit the contents of the task. @@ -395,14 +395,14 @@ C<*info> is the visit info, (see F). */ - VTABLE void visit(visit_info *info) { + VTABLE void visit(PMC *info) { /* 1) visit code block */ VISIT_PMC_ATTR(INTERP, info, SELF, Task, codeblock); } /* -=item C +=item C Used to archive the task. @@ -410,7 +410,7 @@ Used to archive the task. */ - VTABLE void freeze(visit_info *info) { + VTABLE void freeze(PMC *info) { const Parrot_Task_attributes * const core_struct = PARROT_TASK(SELF); /* 1) freeze task id */ @@ -434,7 +434,7 @@ Used to archive the task. /* -=item C +=item C Used to unarchive the task. @@ -442,7 +442,7 @@ Used to unarchive the task. */ - VTABLE void thaw(visit_info *info) { + VTABLE void thaw(PMC *info) { /* 1. thaw task id */ const INTVAL id = VTABLE_shift_integer(INTERP, info); @@ -486,7 +486,7 @@ Used to unarchive the task. /* -=item C +=item C Called after the task has been thawed. @@ -494,7 +494,7 @@ Called after the task has been thawed. */ - VTABLE void thawfinish(visit_info *info) { + VTABLE void thawfinish(PMC *info) { Parrot_Task_attributes * core_struct = PARROT_TASK(SELF); UNUSED(core_struct); /* TODO: Rebuild the task index. */ diff --git a/src/pmc_freeze.c b/src/pmc_freeze.c index 35eef8477a..ab7038d90a 100644 --- a/src/pmc_freeze.c +++ b/src/pmc_freeze.c @@ -18,10 +18,6 @@ C<< pmc->vtable->visit >>, which is called for the first PMC initially. Container PMCs call a "todo-callback" for all contained PMCs. The individual action vtable (freeze/thaw) is then called for all todo-PMCs. -In the current implementation C is a stand-in for some kind of -serializer PMC which will eventually be written. It associates a Parrot -C with a vtable. - =cut */ @@ -30,745 +26,13 @@ C with a vtable. #include "pmc/pmc_callcontext.h" #include "pmc_freeze.str" -/* HEADERIZER HFILE: include/parrot/pmc_freeze.h */ -/* HEADERIZER BEGIN: static */ -/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ - -static void create_buffer(PARROT_INTERP, - ARGIN_NULLOK(PMC *pmc), - ARGMOD(visit_info *info)) - __attribute__nonnull__(1) - __attribute__nonnull__(3) - FUNC_MODIFIES(*info); - -PARROT_INLINE -static void ensure_buffer_size(PARROT_INTERP, - ARGIN(visit_info *io), - size_t len) - __attribute__nonnull__(1) - __attribute__nonnull__(2); - -static INTVAL get_visit_integer(PARROT_INTERP, ARGIN(visit_info *io)) - __attribute__nonnull__(1) - __attribute__nonnull__(2); - -PARROT_INLINE -static INTVAL INFO_HAS_DATA(ARGIN(visit_info *io)) - __attribute__nonnull__(1); - -PARROT_INLINE -static INTVAL OUTPUT_LENGTH(ARGIN(visit_info *io)) - __attribute__nonnull__(1); - -static void push_opcode_integer(PARROT_INTERP, - ARGIN(visit_info *io), - INTVAL v) - __attribute__nonnull__(1) - __attribute__nonnull__(2); - -static void push_opcode_number(PARROT_INTERP, - ARGIN(visit_info *io), - FLOATVAL v) - __attribute__nonnull__(1) - __attribute__nonnull__(2); - -static void push_opcode_string(PARROT_INTERP, - ARGIN(visit_info *io), - ARGIN(STRING *v)) - __attribute__nonnull__(1) - __attribute__nonnull__(2) - __attribute__nonnull__(3); - -static INTVAL shift_opcode_integer(SHIM_INTERP, ARGIN(visit_info *io)) - __attribute__nonnull__(2); - -static FLOATVAL shift_opcode_number(SHIM_INTERP, ARGIN(visit_info *io)) - __attribute__nonnull__(2); - -PARROT_WARN_UNUSED_RESULT -PARROT_CANNOT_RETURN_NULL -static STRING* shift_opcode_string(PARROT_INTERP, ARGIN(visit_info *io)) - __attribute__nonnull__(1) - __attribute__nonnull__(2); - -static void visit_info_init(PARROT_INTERP, - ARGOUT(visit_info *info), - visit_enum_type what, - ARGIN(STRING *input), - ARGIN(PMC *pmc)) - __attribute__nonnull__(1) - __attribute__nonnull__(2) - __attribute__nonnull__(4) - __attribute__nonnull__(5) - FUNC_MODIFIES(*info); - -static void visit_loop_todo_list(PARROT_INTERP, - ARGIN_NULLOK(PMC *current), - ARGIN(visit_info *info)) - __attribute__nonnull__(1) - __attribute__nonnull__(3); - -static void visit_todo_list_freeze(PARROT_INTERP, - ARGIN_NULLOK(PMC* pmc), - ARGIN(visit_info* info)) - __attribute__nonnull__(1) - __attribute__nonnull__(3); - -PARROT_INLINE -static void visit_todo_list_thaw(PARROT_INTERP, - SHIM(PMC* pmc_not_used), - ARGIN(visit_info* info)) - __attribute__nonnull__(1) - __attribute__nonnull__(3); - -#define ASSERT_ARGS_create_buffer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(info)) -#define ASSERT_ARGS_ensure_buffer_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_get_visit_integer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_INFO_HAS_DATA __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_OUTPUT_LENGTH __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_push_opcode_integer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_push_opcode_number __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_push_opcode_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(io) \ - , PARROT_ASSERT_ARG(v)) -#define ASSERT_ARGS_shift_opcode_integer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_shift_opcode_number __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_shift_opcode_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(io)) -#define ASSERT_ARGS_visit_info_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(info) \ - , PARROT_ASSERT_ARG(input) \ - , PARROT_ASSERT_ARG(pmc)) -#define ASSERT_ARGS_visit_loop_todo_list __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(info)) -#define ASSERT_ARGS_visit_todo_list_freeze __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(info)) -#define ASSERT_ARGS_visit_todo_list_thaw __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(interp) \ - , PARROT_ASSERT_ARG(info)) -/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ -/* HEADERIZER END: static */ - /* when thawing a string longer then this size, we first do a GC run and then * block GC - the system can't give us more headers */ #define THAW_BLOCK_GC_SIZE 100000 -/* preallocate freeze image for aggregates with this estimation */ -#define FREEZE_BYTES_PER_ITEM 9 - -/* macros/constants to handle packing/unpacking of PMC IDs and flags - * the 2 LSBs are used for flags, all other bits are used for PMC ID - */ -#define PackID_new(id, flags) (((UINTVAL)(id) * 4) | ((UINTVAL)(flags) & 3)) -#define PackID_get_PMCID(id) ((UINTVAL)(id) / 4) -#define PackID_set_PMCID(lv, id) (lv) = PackID_new((id), PackID_get_FLAGS(lv)) -#define PackID_get_FLAGS(id) ((UINTVAL)(id) & 3) -#define PackID_set_FLAGS(lv, flags) (lv) = PackID_new(PackID_get_PMCID(lv), (flags)) - -enum { - enum_PackID_normal = 0, - enum_PackID_seen = 1, -}; - -/* - -=head2 C IO Functions - -=over 4 - -=item C - -Checks the size of the "stream" buffer to see if it can accommodate -C more bytes. If not, expands the buffer. - -=cut - -*/ - -#define GET_VISIT_CURSOR(io) \ - ((opcode_t *)(((char *)Buffer_bufstart((io)->buffer) + (io)->pos))) -#define SET_VISIT_CURSOR(io, x) do {\ - (io)->pos = ((char *)(x) - (char *)Buffer_bufstart((io)->buffer)); \ -} while (0) -#define INC_VISIT_CURSOR(io, x) do {\ - (io)->pos += (x); \ -} while (0) - -#define BYTECODE_SHIFT_OK(io) PARROT_ASSERT((io)->pos <= (io)->input_length) - - -PARROT_INLINE -static void -ensure_buffer_size(PARROT_INTERP, ARGIN(visit_info *io), size_t len) -{ - ASSERT_ARGS(ensure_buffer_size) - Buffer *buf = io->buffer; - const size_t used = io->pos; - const int need_free = Buffer_buflen(buf) - used - len; - - /* grow by factor 1.5 or such */ - if (need_free <= 16) { - size_t new_size = (size_t) (Buffer_buflen(buf) * 1.5); - if (new_size < Buffer_buflen(buf) - need_free + 512) - new_size = Buffer_buflen(buf) - need_free + 512; - Parrot_gc_reallocate_buffer_storage(interp, buf, new_size); - - PARROT_ASSERT(Buffer_buflen(buf) - used - len >= 15); - } - -#ifndef DISABLE_GC_DEBUG - Parrot_gc_compact_memory_pool(interp); -#endif - -} - -/* - -=item C - -XXX TODO - -=cut - -*/ - -PARROT_INLINE -static INTVAL -OUTPUT_LENGTH(ARGIN(visit_info *io)) { - ASSERT_ARGS(OUTPUT_LENGTH) - return io->pos; -} - -/* - -=item C - -XXX TODO - -=cut - -*/ - -PARROT_INLINE -static INTVAL -INFO_HAS_DATA(ARGIN(visit_info *io)) { - ASSERT_ARGS(INFO_HAS_DATA) - return io->pos < io->input_length; -} - - -/* - -=item C - -get the flags describing the visit action - -=cut - -*/ - -static INTVAL -get_visit_integer(PARROT_INTERP, ARGIN(visit_info *io)) { - ASSERT_ARGS(get_visit_integer) - return io->what; -} - -/* - -=item C - -Pushes the integer C onto the end of the C<*io> "stream". - -XXX assumes sizeof (opcode_t) == sizeof (INTVAL). - -=cut - -*/ - -static void -push_opcode_integer(PARROT_INTERP, ARGIN(visit_info *io), INTVAL v) -{ - ASSERT_ARGS(push_opcode_integer) - size_t len = PF_size_integer() * sizeof (opcode_t); - ensure_buffer_size(interp, io, len); - SET_VISIT_CURSOR(io, PF_store_integer(GET_VISIT_CURSOR(io), v)); -} - - -/* - -=item C - -Pushes the number C onto the end of the C<*io> "stream". - -=cut - -*/ - -static void -push_opcode_number(PARROT_INTERP, ARGIN(visit_info *io), FLOATVAL v) -{ - ASSERT_ARGS(push_opcode_number) - size_t len = PF_size_number() * sizeof (opcode_t); - ensure_buffer_size(interp, io, len); - SET_VISIT_CURSOR(io, PF_store_number(GET_VISIT_CURSOR(io), &v)); -} - - -/* - -=item C - -Pushes the string C<*v> onto the end of the C<*io> "stream". - -=cut - -*/ - -static void -push_opcode_string(PARROT_INTERP, ARGIN(visit_info *io), ARGIN(STRING *v)) -{ - ASSERT_ARGS(push_opcode_string) - size_t len = PF_size_string(v) * sizeof (opcode_t); - ensure_buffer_size(interp, io, len); - SET_VISIT_CURSOR(io, PF_store_string(GET_VISIT_CURSOR(io), v)); -} - -/* - -=item C - -Pushes a reference to pmc C<*v> onto the end of the C<*io> "stream". If C<*v> -hasn't been seen yet, it is also pushed onto the todo list. - -=cut - -*/ - -static void -push_opcode_pmc(PARROT_INTERP, ARGIN(visit_info *io), ARGIN(PMC *v)) { - io->thaw_ptr = &v; - (io->visit_pmc_now)(interp, v, io); -} - -/* - -=item C - -Removes and returns an integer from the start of the C<*io> "stream". - -=cut - -*/ - -static INTVAL -shift_opcode_integer(SHIM_INTERP, ARGIN(visit_info *io)) -{ - ASSERT_ARGS(shift_opcode_integer) - opcode_t *pos = GET_VISIT_CURSOR(io); - const INTVAL i = PF_fetch_integer(io->pf, (const opcode_t **)&pos); - SET_VISIT_CURSOR(io, pos); - BYTECODE_SHIFT_OK(io); - return i; -} - - /* -=item C - -Removes and returns an number from the start of the C<*io> "stream". - -=cut - -*/ - -static FLOATVAL -shift_opcode_number(SHIM_INTERP, ARGIN(visit_info *io)) -{ - ASSERT_ARGS(shift_opcode_number) - opcode_t *pos = GET_VISIT_CURSOR(io); - const FLOATVAL f = PF_fetch_number(io->pf, (const opcode_t **)&pos); - SET_VISIT_CURSOR(io, pos); - BYTECODE_SHIFT_OK(io); - return f; -} - - -/* - -=item C - -Removes and returns a string from the start of the C<*io> "stream". - -=cut - -*/ - - -PARROT_WARN_UNUSED_RESULT -PARROT_CANNOT_RETURN_NULL -static STRING* -shift_opcode_string(PARROT_INTERP, ARGIN(visit_info *io)) -{ - ASSERT_ARGS(shift_opcode_string) - opcode_t *pos = GET_VISIT_CURSOR(io); - STRING * const s = PF_fetch_string(interp, io->pf, (const opcode_t **)&pos); - SET_VISIT_CURSOR(io, pos); - BYTECODE_SHIFT_OK(io); - return s; -} - -/* - -=item C - -Removes and returns a reference to a pmc from the start of the C<*io> "stream". - -=cut - -*/ - -PARROT_WARN_UNUSED_RESULT -PARROT_CANNOT_RETURN_NULL -static PMC * -shift_opcode_pmc(PARROT_INTERP, ARGIN(visit_info *io)) { - PMC *result; - io->thaw_ptr = &result; - (io->visit_pmc_now)(interp, NULL, io); - return result; -} - -/* - -=back - -=head2 Helper Functions - -=over 4 - -=cut - -*/ - -/* - * this function setup stuff may be replaced by a real PMC - * in the future - * TODO add read/write header functions, e.g. vtable->init_pmc - */ - -static image_funcs opcode_funcs = { - get_visit_integer, - push_opcode_integer, - push_opcode_string, - push_opcode_number, - push_opcode_pmc, - shift_opcode_integer, - shift_opcode_string, - shift_opcode_number, - shift_opcode_pmc -}; - -/* - -=item C - -Initializes the C<*info> lists. - -=cut - -*/ -#define GROW_TO_16_BYTE_BOUNDARY(size) ((size) + ((size) % 16 ? 16 - (size) % 16 : 0)) - -static void -visit_info_init(PARROT_INTERP, ARGOUT(visit_info *info), - visit_enum_type what, ARGIN(STRING *input), ARGIN(PMC *pmc)) -{ - ASSERT_ARGS(visit_info_init) - /* We want to store a 16-byte aligned header, but the actual * header may be shorter. */ - const unsigned int header_length = GROW_TO_16_BYTE_BOUNDARY(PACKFILE_HEADER_BYTES); - - PackFile *pf = info->pf = PackFile_new(interp, 0); - info->what = what; - info->vtable = &opcode_funcs; - info->image_io = info; /* backwards-compat hack */ - - if (info->what == VISIT_FREEZE_NORMAL) { - info->visit_pmc_now = visit_todo_list_freeze; - create_buffer(interp, pmc, info); - ensure_buffer_size(interp, info, header_length); - mem_sys_memcopy(GET_VISIT_CURSOR(info), pf->header, PACKFILE_HEADER_BYTES); - INC_VISIT_CURSOR(info, header_length); - } - else { /* VISIT_THAW_ */ - int unpacked_length; - info->visit_pmc_now = visit_todo_list_thaw; - info->buffer = (Buffer *)input; - PARROT_ASSERT(input->_bufstart == input->strstart); - SET_VISIT_CURSOR(info, Buffer_bufstart(info->buffer)); - info->input_length = input->strlen; - - pf->options |= PFOPT_PMC_FREEZE_ONLY; - unpacked_length = PackFile_unpack(interp, pf, GET_VISIT_CURSOR(info), info->input_length); - if (!unpacked_length) { - PackFile_destroy(interp, info->pf); - Parrot_ex_throw_from_c_args(interp, NULL, - EXCEPTION_INVALID_STRING_REPRESENTATION, - "PackFile header failed during unpack"); - } - else { - INC_VISIT_CURSOR(info, header_length); - } - } - - /* we must use PMCs here so that they get marked properly */ - info->todo = pmc_new(interp, enum_class_ResizablePMCArray); - if (info->what == VISIT_FREEZE_NORMAL) { - info->seen = pmc_new(interp, enum_class_Hash); - VTABLE_set_pointer(interp, info->seen, parrot_new_intval_hash(interp)); - info->id_list = PMCNULL; - } - else { - info->seen = PMCNULL; - info->id_list = pmc_new(interp, enum_class_ResizablePMCArray); - } - info->id = 0; - info->extra_flags = EXTRA_IS_NULL; - - visit_loop_todo_list(interp, pmc, info); - PackFile_destroy(interp, info->pf); -} - - -PARROT_INLINE -static PMC* -id_list_get(PARROT_INTERP, ARGIN(visit_info *info), UINTVAL id) { - PMC *pos = VTABLE_get_pmc_keyed_int(interp, info->id_list, id); - - if (pos && pos != ((void *)-1)) - return pos; - return NULL; -} - -/* - -=item C - -Callback for thaw - action first. -thaws and return a PMC. - -=cut - -*/ - -PARROT_INLINE -static void -visit_todo_list_thaw(PARROT_INTERP, SHIM(PMC* pmc_not_used), ARGIN(visit_info* info)) -{ - ASSERT_ARGS(visit_todo_list_thaw) - - UINTVAL n = VTABLE_shift_integer(interp, info); - UINTVAL id = PackID_get_PMCID(n); - int packid_flags = PackID_get_FLAGS(n); - PMC *pmc = PMCNULL; - - PARROT_ASSERT(info->what == VISIT_THAW_NORMAL); - - switch (packid_flags) { - case enum_PackID_seen: - if (id) /* got a non-NULL PMC */ - pmc = id_list_get(interp, info, id); - break; - case enum_PackID_normal: - { - INTVAL type = VTABLE_shift_integer(interp, info); - if (type <= 0 || type > interp->n_vtable_max) - Parrot_ex_throw_from_c_args(interp, NULL, 1, "Unknown PMC type to thaw %d", type); - - pmc = pmc_new_noinit(interp, type); - VTABLE_thaw(interp, pmc, info); - - VTABLE_set_pmc_keyed_int(interp, info->id_list, id, pmc); - /* remember nested aggregates depth first */ - VTABLE_unshift_pmc(interp, info->todo, pmc); - } - break; - default: - Parrot_ex_throw_from_c_args(interp, NULL, 1, "Unknown PMC id args thaw %d", packid_flags); - break; - } - - *info->thaw_ptr = pmc; -} - - -/* - -=item C - -Checks the seen PMC via the todo list. - -=cut - -*/ - -static void -visit_todo_list_freeze(PARROT_INTERP, ARGIN_NULLOK(PMC* pmc), ARGIN(visit_info* info)) -{ - ASSERT_ARGS(visit_todo_list_freeze) - UINTVAL id; - int packid_type; - - PARROT_ASSERT(info->what == VISIT_FREEZE_NORMAL); - - if (PMC_IS_NULL(pmc)) { - id = 0; - packid_type = enum_PackID_seen; - } - else { - Hash *hash = (Hash *)VTABLE_get_pointer(interp, info->seen); - HashBucket * const b = parrot_hash_get_bucket(interp, hash, pmc); - if (b) { - id = (UINTVAL) b->value; - packid_type = enum_PackID_seen; - } - else { - info->id++; /* next id to freeze */ - id = info->id; - packid_type = enum_PackID_normal; - } - } - - VTABLE_push_integer(interp, info, PackID_new(id, packid_type)); - - if (packid_type == enum_PackID_normal) { - Hash *hash = (Hash *)VTABLE_get_pointer(interp, info->seen); - PARROT_ASSERT(pmc); - VTABLE_push_integer(interp, info, - PObj_is_object_TEST(pmc) ? enum_class_Object : pmc->vtable->base_type); - parrot_hash_put(interp, hash, pmc, (void *)id); - VTABLE_unshift_pmc(interp, info->todo, pmc); - VTABLE_freeze(interp, pmc, info); - } -} - - -/* - -=item C - -The thaw loop. - -=cut - -*/ - -static void -visit_loop_todo_list(PARROT_INTERP, ARGIN_NULLOK(PMC *current), - ARGIN(visit_info *info)) -{ - ASSERT_ARGS(visit_loop_todo_list) - const int thawing = (info->what == VISIT_THAW_NORMAL); - PMC * const todolist = info->todo; - - (info->visit_pmc_now)(interp, current, info); - - /* can't cache upper limit, visit may append items */ - while (VTABLE_elements(interp, todolist)) { - current = VTABLE_shift_pmc(interp, todolist); - if (!current) - Parrot_ex_throw_from_c_args(interp, NULL, 1, - "NULL current PMC in visit_loop_todo_list"); - - PARROT_ASSERT(current->vtable); - VTABLE_visit(interp, current, info); - VISIT_PMC(interp, info, PMC_metadata(current)); - } - - if (thawing) - /* we're done reading the image */ - PARROT_ASSERT(!INFO_HAS_DATA(info)); - - if (thawing) { - /* on thawing call thawfinish for each processed PMC */ - const INTVAL n = VTABLE_elements(interp, info->id_list); - int i; - - /* Thaw in reverse order. We have to fully thaw younger PMCs before use them in older */ - for (i = n-1; i >= 0; --i) { - current = VTABLE_get_pmc_keyed_int(interp, info->id_list, i); - if (!PMC_IS_NULL(current)) - VTABLE_thawfinish(interp, current, info); - } - } -} - - -/* - -=item C - -Allocate buffer to some estimated size. - -=cut - -*/ - -static void -create_buffer(PARROT_INTERP, ARGIN_NULLOK(PMC *pmc), ARGMOD(visit_info *info)) -{ - ASSERT_ARGS(create_buffer) - STRING *array = CONST_STRING(interp, "array"); - STRING *hash = CONST_STRING(interp, "hash"); - INTVAL len; - - if (!PMC_IS_NULL(pmc) - && (VTABLE_does(interp, pmc, array) || VTABLE_does(interp, pmc, hash))) { - const INTVAL items = VTABLE_elements(interp, pmc); - /* TODO check e.g. first item of aggregate and estimate size */ - len = (items ? items : 1) * FREEZE_BYTES_PER_ITEM; - } - else - len = FREEZE_BYTES_PER_ITEM; - - info->buffer = (Buffer *)Parrot_gc_new_bufferlike_header(interp, sizeof (Buffer)); - Parrot_gc_allocate_buffer_storage_aligned(interp, info->buffer, len); - SET_VISIT_CURSOR(info, Buffer_bufstart(info->buffer)); -} - - -/* - -=back - =head2 Public Interface =over 4 @@ -788,10 +52,9 @@ STRING* Parrot_freeze(PARROT_INTERP, ARGIN(PMC *pmc)) { ASSERT_ARGS(Parrot_freeze) - visit_info info; - - visit_info_init(interp, &info, VISIT_FREEZE_NORMAL, STRINGNULL, pmc); - return Parrot_str_new_from_buffer(interp, info.buffer, OUTPUT_LENGTH(&info)); + PMC *image = pmc_new(interp, enum_class_ImageIO); + VTABLE_set_pmc(interp, image, pmc); + return VTABLE_get_string(interp, image); } @@ -819,7 +82,7 @@ Parrot_thaw(PARROT_INTERP, ARGIN(STRING *image)) { ASSERT_ARGS(Parrot_thaw) - visit_info info; + PMC *info = pmc_new(interp, enum_class_ImageIO); int gc_block = 0; PMC *result; @@ -840,9 +103,8 @@ Parrot_thaw(PARROT_INTERP, ARGIN(STRING *image)) gc_block = 1; } - info.thaw_ptr = &result; - visit_info_init(interp, &info, VISIT_THAW_NORMAL, image, PMCNULL); - BYTECODE_SHIFT_OK(&info); + VTABLE_set_pointer(interp, info, &result); + VTABLE_set_string_native(interp, info, image); if (gc_block) { Parrot_unblock_GC_mark(interp); diff --git a/src/vtable.tbl b/src/vtable.tbl index cea046f9c9..a8ac68ebf5 100644 --- a/src/vtable.tbl +++ b/src/vtable.tbl @@ -348,10 +348,10 @@ void remove_vtable_override(STRING* vtable_name) :write PMC* inspect() PMC* inspect_str(STRING* what) -void freeze(visit_info* info) -void thaw (visit_info* info) :write -void thawfinish (visit_info* info) :write -void visit (visit_info* info) +void freeze(PMC* info) +void thaw (PMC* info) :write +void thawfinish (PMC* info) :write +void visit (PMC* info) void share() diff --git a/t/native_pbc/annotations.pbc b/t/native_pbc/annotations.pbc index 3dd1b9aca6..392f2ef462 100644 Binary files a/t/native_pbc/annotations.pbc and b/t/native_pbc/annotations.pbc differ diff --git a/t/native_pbc/integer_1.pbc b/t/native_pbc/integer_1.pbc index c5304d9083..8e1a839a65 100644 Binary files a/t/native_pbc/integer_1.pbc and b/t/native_pbc/integer_1.pbc differ diff --git a/t/native_pbc/number_1.pbc b/t/native_pbc/number_1.pbc index 1ebc390a1f..6043c20a89 100644 Binary files a/t/native_pbc/number_1.pbc and b/t/native_pbc/number_1.pbc differ diff --git a/t/native_pbc/string_1.pbc b/t/native_pbc/string_1.pbc index 9f1591f7c1..353d367e62 100644 Binary files a/t/native_pbc/string_1.pbc and b/t/native_pbc/string_1.pbc differ