parrotcode: Freeze and thaw functionality | |
Contents | C |
src/pmc_freeze.c - Freeze and thaw functionality
Freeze uses the next_for_GC pointer()
to remember seen PMCs.
PMCs are written as IDs (or tags),
which are calculated from their arena address.
This PMC number is multiplied by four.
The 2 low bits indicate a seen PMC or a PMC of the same type as the previous one respectively.
Thawing PMCs uses a list with (maximum) size of the amount of PMCs to keep track of retrieved PMCs.
The individual information of PMCs is frozen/thawed by their vtables.
To avoid recursion,
the whole functionality is driven by 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 IMAGE_IO
is a stand-in for some kind of serializer PMC which will eventually be written.
It associates a Parrot STRING
with a vtable.
static void str_append(Parrot_Interp interp, STRING *s, const void *b, size_t len)
len
bytes from buffer *b
to string *s
.static void push_ascii_integer(Parrot_Interp interp, IMAGE_IO *io, INTVAL v)
v
onto the end of the *io
"stream".static void push_ascii_number(Parrot_Interp interp, IMAGE_IO *io, FLOATVAL v)
v
onto the end of the *io
"stream".static void push_ascii_string(Parrot_Interp interp, IMAGE_IO *io, STRING *s)
*s
onto the end of the *io
"stream".static void push_ascii_pmc(Parrot_Interp interp, IMAGE_IO *io, PMC *v)
*v
onto the end of the *io
"stream".static INTVAL shift_ascii_integer(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".static FLOATVAL shift_ascii_number(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".static STRING *shift_ascii_string(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".static PMC *shift_ascii_pmc(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".opcode_t
IO Functions static PARROT_INLINE void op_check_size(Parrot_Interp interp, STRING *s, size_t len)
len
more bytes.
If not then the buffer is expanded.static void op_append(Parrot_Interp interp, STRING *s, opcode_t b, size_t len)
b
to the string *s
.static void push_opcode_integer(Parrot_Interp interp, IMAGE_IO *io, INTVAL v)
v
onto the end of the *io
"stream".static void push_opcode_number(Parrot_Interp interp, IMAGE_IO *io, FLOATVAL v)
v
onto the end of the *io
"stream".static void push_opcode_string(Parrot_Interp interp, IMAGE_IO *io, STRING *v)
*v
onto the end of the *io
"stream".static void push_opcode_pmc(Parrot_Interp interp, IMAGE_IO *io, PMC *v)
*v
onto the end of the *io
"stream".static INTVAL shift_opcode_integer(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".static PMC *shift_opcode_pmc(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".tatic FLOATVAL shift_opcode_number(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".static STRING *shift_opcode_string(Parrot_Interp interp, IMAGE_IO *io)
*io
"stream".static void pmc_add_ext(Parrot_Interp interp, PMC *pmc)
PMC_EXT
to *pmc
.static void cleanup_next_for_GC_pool(Parrot_Interp interp, struct Small_Object_Pool *pool)
next_for_GC
pointers to NULL
.static void cleanup_next_for_GC(Parrot_Interp interp)
next_for_GC
pointers.static void ft_init(Parrot_Interp interp, visit_info *info)
static void todo_list_init(Parrot_Interp interp, visit_info *info)
*info
lists.PARROT_INLINE static void freeze_pmc(Parrot_Interp interp, PMC *pmc, visit_info *info, int seen, UINTVAL id)
PARROT_INLINE static int thaw_pmc(Parrot_Interp interp, visit_info *info, UINTVAL *id, INTVAL *type)
Array
class_enum_Array
,
33 is class_enum_Integer
,
the type of the second Integer
is suppressed,
the repeated P0 has bit 0 set.PARROT_INLINE static void do_action(Parrot_Interp interp, PMC *pmc, visit_info *info, int seen, UINTVAL id)
visit_next_for_GC()
and visit_todo_list()
to perform the action specified in info->what
.VISIT_FREEZE_NORMAL
is implemented.PARROT_INLINE static PMC *thaw_create_pmc(Parrot_Interp interp, PMC *pmc, visit_info *info, INTVAL type)
do_thaw()
to attach the vtable etc.
to *pmc
.PARROT_INLINE static void do_thaw(Parrot_Interp interp, PMC *pmc, visit_info *info)
visit_todo_list_thaw()
to thaw and return a PMC.seen
is false if this is the first time the PMC has been encountered.static void add_pmc_next_for_GC(Parrot_Interp interp, PMC *pmc, visit_info *info)
PARROT_INLINE static int next_for_GC_seen(Parrot_Interp interp, PMC *pmc, visit_info *info, UINTVAL *id)
next_for_GC pointer
generate a unique ID per PMC and freeze the ID (not the PMC address) so thaw the hash-lookup can be replaced by an array lookup then which is a lot faster.static void add_pmc_todo_list(Parrot_Interp interp, PMC *pmc, visit_info *info)
PARROT_INLINE static int todo_list_seen(Parrot_Interp interp, PMC *pmc, visit_info *info, UINTVAL *id)
static void visit_next_for_GC(Parrot_Interp interp, PMC *pmc, visit_info *info)
visit_child
callbacks:static void visit_todo_list(Parrot_Interp interp, PMC *pmc, visit_info *info)
static void visit_todo_list_thaw(Parrot_Interp interp, PMC *old, visit_info *info)
do_thaw()
.static void visit_loop_next_for_GC(Parrot_Interp interp, PMC *current, visit_info *info)
static PMC *visit_loop_todo_list(Parrot_Interp interp, PMC *current, visit_info *info)
static void create_image(Parrot_Interp interp, PMC *pmc, visit_info *info)
static PMC *run_thaw(Parrot_Interp interp, STRING *image, visit_enum_type what)
what
indicates what to be thawed.next_for_GC
pointers as todo-list too,
but this would need 2 runs through the arenas to clean the next_for_GC
pointers.next_for_GC
approach could be a win.STRING *Parrot_freeze_at_destruct(Parrot_Interp interp, PMC *pmc)
next_for_GC
pointer,
so its not reentrant and must not be interrupted by a DOD run.STRING *Parrot_freeze(Parrot_Interp interp, PMC *pmc)
PMC *Parrot_thaw(Parrot_Interp interp, STRING *image)
thaw
opcode.PMC *Parrot_thaw_constants(Parrot_Interp interp, STRING *image)
PMC *Parrot_clone(Parrot_Interp interp, PMC *pmc)
The seen-hash version for freezing might go away sometimes.
Lot of discussion on p6i and docs/dev/pmc_freeze.pod.
Initial version by leo 2003.11.03 - 2003.11.07.
|