NAME
src/pmc_freeze.c - Freeze and thaw functionality
DESCRIPTION
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.
Image Stream Functions
static void str_append
Appends static void push_ascii_integer
Pushes an ASCII version of the integer static void push_ascii_number
Pushes an ASCII version of the number static void push_ascii_string
Pushes an ASCII version of the string static void push_ascii_pmc
Pushes an ASCII version of the PMC static INTVAL shift_ascii_integer
Removes and returns an integer from the start of the static FLOATVAL shift_ascii_number
Removes and returns an number from the start of the static STRING *shift_ascii_string
Removes and returns an string from the start of the static PMC *shift_ascii_pmc
Removes and returns a PMC from the start of the
len
bytes from buffer *b
to string *s
.Plain ascii - for testing only:For speed reasons we mess around with the string buffers directly.No encoding of strings,
no transcoding.
v
onto the end of the *io
"stream".
v
onto the end of the *io
"stream".
*s
onto the end of the *io
"stream".For testing only - no encodings and such.XXX no string delimiters - so no space allowed.
*v
onto the end of the *io
"stream".
*io
"stream".
*io
"stream".
*io
"stream".
*io
"stream".opcode_t
IO Functions
static void op_check_size
Checks the size of the "stream" buffer to see if it can accommodate static void op_append
Appends the opcode static void push_opcode_integer
Pushes the integer static void push_opcode_number
Pushes the number static void push_opcode_string
Pushes the string static void push_opcode_pmc
Pushes the PMC static INTVAL shift_opcode_integer
Removes and returns an integer from the start of the static PMC *shift_opcode_pmc
Removes and returns an PMC from the start of the static FLOATVAL shift_opcode_number
Removes and returns an number from the start of the static STRING *shift_opcode_string
Removes and returns a string from the start of the
len
more bytes.
If not then the buffer is expanded.
b
to the string *s
.
v
onto the end of the *io
"stream".XXX assumes sizeof (opcode_t) == sizeof (INTVAL).
v
onto the end of the *io
"stream".
*v
onto the end of the *io
"stream".
*v
onto the end of the *io
"stream".
*io
"stream".TODO - The shift functions aren't portable yet.
We need to have a packfile header for wordsize and endianess.
*io
"stream".Note that this actually reads a PMC id,
not a PMC.
*io
"stream".
*io
"stream".Helper Functions
static void pmc_add_ext
Adds a static void cleanup_next_for_GC_pool
Sets all the static void cleanup_next_for_GC
Cleans up the static void ft_init
Initializes the freeze/thaw subsystem.
static void todo_list_init
Initializes the static void freeze_pmc
Freeze PMC,
setting type,
seen,
and "same-as-last" indicators as appropriate.
static int thaw_pmc
Freeze and thaw a PMC (id).For example,
the ASCII representation of the static void do_action
Called from static PMC *thaw_create_pmc
Called from static void do_thaw
Called by static UINTVAL id_from_pmc
Find a PMC in an arena, and return an id (left-shifted 2 bits), based on its position.If not found, throw an exception.
static void add_pmc_next_for_GC
Remembers the PMC for later processing.
static int next_for_GC_seen
Remembers next child to visit via the static void add_pmc_todo_list
Remembers the PMC to be processed later.
static int todo_list_seen
Returns true if the PMC was seen, otherwise it put it on the todo list, generates an ID (tag) for PMC, offset by 4 as are addresses, low bits are flags.
static void visit_next_for_GC
static void visit_todo_list
Checks the seen PMC via the todo list.
static void visit_todo_list_thaw
Callback for thaw - action first.Todo-list and seen handling is all in static void visit_loop_next_for_GC
Put first item on todo list, then run as long as there are items to be done.
static void visit_loop_todo_list
The thaw loop.
static void create_image
Allocate image to some estimated size.
static PMC *run_thaw
Performs thawing.
PMC_EXT
to *pmc
.
next_for_GC
pointers to NULL
.
next_for_GC
pointers.
*info
lists.
Array
P0 = [P1=666, P2=777, P0]may look like this:
0xdf4 30 3 0xdf8 33 666 0xdf2 777 0xdf5where 30 is
class_enum_Array
, 33 is class_enum_Integer
, the type of the second Integer
is suppressed, the repeated P0 has bit 0 set.
visit_next_for_GC()
and visit_todo_list()
to perform the action specified in info->what
.Currently only VISIT_FREEZE_NORMAL
is implemented.
do_thaw()
to attach the vtable etc. to *pmc
.
visit_todo_list_thaw()
to thaw and return a PMC.seen
is false if this is the first time the PMC has been encountered.
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.
visit_child
callbacks:Checks if the PMC was seen, generate an ID for it if not, then do the appropriate action.
do_thaw()
.
what
indicates what to be thawed.Thaw could use the next_for_GC
pointers as todo-list too, but this would need 2 runs through the arenas to clean the next_for_GC
pointers.For now it seems cheaper to use a list for remembering contained aggregates. We could of course decide dynamically, which strategy to use, e.g.: given a big image, the first thawed item is a small aggregate. This implies, it probably contains (or some big strings) more nested containers, for which the next_for_GC
approach could be a win.Public Interface
STRING *Parrot_freeze_at_destruct
This function must not consume any resources (except the image itself). It uses the STRING *Parrot_freeze
Freeze using either method.
PMC *Parrot_thaw
Thaw a PMC, called from the PMC *Parrot_thaw_constants
Thaw the constants. This is used by PackFile for unpacking PMC constants.
PMC *Parrot_clone
There are for sure shortcuts to clone faster, e.g. always thaw the image immediately or use a special callback. But for now we just thaw a frozen PMC.
next_for_GC
pointer, so its not reentrant and must not be interrupted by a GC run.
thaw
opcode.
TODO
The seen-hash version for freezing might go away sometimes.
SEE ALSO
Lot of discussion on p6i and docs/dev/pmc_freeze.pod.
HISTORY
Initial version by leo 2003.11.03 - 2003.11.07.