| 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, NOTNULL(STRING *s), ARGIN(const void *b), size_t len)len bytes from buffer *b to string *s.static void push_ascii_integer(PARROT_INTERP, NOTNULL(IMAGE_IO *io), INTVAL v)v onto the end of the *io "stream".static void push_ascii_number(PARROT_INTERP, NOTNULL(IMAGE_IO *io), FLOATVAL v)v onto the end of the *io "stream".static void push_ascii_string(PARROT_INTERP, NOTNULL(IMAGE_IO *io), NOTNULL(STRING *s))*s onto the end of the *io "stream".static void push_ascii_pmc(PARROT_INTERP, NOTNULL(IMAGE_IO *io), ARGIN(const PMC *v))*v onto the end of the *io "stream".static INTVAL shift_ascii_integer(SHIM_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".static FLOATVAL shift_ascii_number(SHIM_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL static STRING *shift_ascii_string(PARROT_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL static PMC *shift_ascii_pmc(SHIM_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".opcode_t IO Functions 
PARROT_INLINE static void op_check_size(PARROT_INTERP, NOTNULL(STRING *s), size_t len)len more bytes.
If not then the buffer is expanded.static void op_append(PARROT_INTERP, NOTNULL(STRING *s), opcode_t b, size_t len)b to the string *s.static void push_opcode_integer(PARROT_INTERP, NOTNULL(IMAGE_IO *io), INTVAL v)v onto the end of the *io "stream".static void push_opcode_number(PARROT_INTERP, NOTNULL(IMAGE_IO *io), FLOATVAL v)v onto the end of the *io "stream".static void push_opcode_string(PARROT_INTERP, NOTNULL(IMAGE_IO *io), NOTNULL(STRING *v))*v onto the end of the *io "stream".static void push_opcode_pmc(PARROT_INTERP, NOTNULL(IMAGE_IO *io), NOTNULL(PMC *v))*v onto the end of the *io "stream".static INTVAL shift_opcode_integer(SHIM_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL static PMC *shift_opcode_pmc(PARROT_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".static FLOATVAL shift_opcode_number(SHIM_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL static STRING *shift_opcode_string(PARROT_INTERP, NOTNULL(IMAGE_IO *io))*io "stream".
static void pmc_add_ext(PARROT_INTERP, NOTNULL(PMC *pmc))PMC_EXT to *pmc.static void cleanup_next_for_GC_pool(NOTNULL(Small_Object_Pool *pool))next_for_GC pointers to NULL.static void cleanup_next_for_GC(PARROT_INTERP)next_for_GC pointers.static void ft_init(PARROT_INTERP, NOTNULL(visit_info *info))static void todo_list_init(PARROT_INTERP, NOTNULL(visit_info *info))*info lists.PARROT_INLINE static void freeze_pmc(PARROT_INTERP, NULLOK(PMC *pmc), NOTNULL(visit_info *info), int seen, UINTVAL id)PARROT_INLINE static int thaw_pmc(PARROT_INTERP, NOTNULL(visit_info *info), NOTNULL(UINTVAL *id), NOTNULL(INTVAL *type))Array P0 = [P1=666, P2=777, P0]
0xdf4 30 3 0xdf8 33 666 0xdf2 777 0xdf5
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, NULLOK(PMC *pmc), NOTNULL(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 PARROT_CANNOT_RETURN_NULL static PMC *thaw_create_pmc(PARROT_INTERP, ARGIN(const visit_info *info), INTVAL type)do_thaw() to attach the vtable etc. to *pmc.PARROT_INLINE static void do_thaw(PARROT_INTERP, NOTNULL(PMC *pmc), NOTNULL(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 UINTVAL id_from_pmc(PARROT_INTERP, NOTNULL(PMC *pmc))static void add_pmc_next_for_GC(SHIM_INTERP, NOTNULL(PMC *pmc), NOTNULL(visit_info *info))PARROT_INLINE static int next_for_GC_seen(PARROT_INTERP, NULLOK(PMC *pmc), NOTNULL(visit_info *info), NOTNULL(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, NULLOK(PMC *pmc), NOTNULL(visit_info *info))PARROT_INLINE static int todo_list_seen(PARROT_INTERP, NOTNULL(PMC *pmc), NOTNULL(visit_info *info), NOTNULL(UINTVAL *id))static void visit_next_for_GC(PARROT_INTERP, NOTNULL(PMC *pmc), NOTNULL(visit_info *info))visit_child callbacks:static void visit_todo_list(PARROT_INTERP, NOTNULL(PMC *pmc), NOTNULL(visit_info *info))static void visit_todo_list_thaw(PARROT_INTERP, NOTNULL(PMC *old), NOTNULL(visit_info *info))do_thaw().static void visit_loop_next_for_GC(PARROT_INTERP, NOTNULL(PMC *current), NOTNULL(visit_info *info))static void visit_loop_todo_list(PARROT_INTERP, NULLOK(PMC *current), NOTNULL(visit_info *info))static void create_image(PARROT_INTERP, NULLOK(PMC *pmc), NOTNULL(visit_info *info))PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL static PMC *run_thaw(PARROT_INTERP, NOTNULL(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.
PARROT_API PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL STRING *Parrot_freeze_at_destruct(PARROT_INTERP, NOTNULL(PMC *pmc))next_for_GC pointer, so its not reentrant and must not be interrupted by a DOD run.PARROT_API PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL STRING *Parrot_freeze(PARROT_INTERP, NOTNULL(PMC *pmc))PARROT_API PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL PMC *Parrot_thaw(PARROT_INTERP, NOTNULL(STRING *image))thaw opcode.PARROT_API PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL PMC *Parrot_thaw_constants(PARROT_INTERP, NOTNULL(STRING *image))PARROT_API PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL PMC *Parrot_clone(PARROT_INTERP, NOTNULL(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.
|
|
|