[svn:parrot] r44756 - in branches/tt1015/src: . ops pmc
plobsing at svn.parrot.org
plobsing at svn.parrot.org
Mon Mar 8 15:08:17 UTC 2010
Author: plobsing
Date: Mon Mar 8 15:08:13 2010
New Revision: 44756
URL: https://trac.parrot.org/parrot/changeset/44756
Log:
first cut of cloning visitor
Seems to work mostly. Now must fix all PMCs that either provide *different*
functionality through clone than through freeze, or flat out don't provide
freeze. Bad PMCs!
Added:
branches/tt1015/src/pmc/visitclone.pmc
Modified:
branches/tt1015/src/ops/set.ops
branches/tt1015/src/pmc_freeze.c
Modified: branches/tt1015/src/ops/set.ops
==============================================================================
--- branches/tt1015/src/ops/set.ops Mon Mar 8 11:08:50 2010 (r44755)
+++ branches/tt1015/src/ops/set.ops Mon Mar 8 15:08:13 2010 (r44756)
@@ -471,7 +471,7 @@
=cut
inline op clone(out PMC, invar PMC) :base_mem {
- $1 = VTABLE_clone(interp, $2);
+ $1 = Parrot_clone(interp, $2);
}
=item B<clone>(out PMC, invar PMC, in PMC)
Added: branches/tt1015/src/pmc/visitclone.pmc
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/tt1015/src/pmc/visitclone.pmc Mon Mar 8 15:08:13 2010 (r44756)
@@ -0,0 +1,360 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id: imageiosize.pmc 44214 2010-02-20 02:01:10Z plobsing $
+
+=head1 NAME
+
+src/pmc/visitclone.pmc - VisitClone PMC
+
+=head1 DESCRIPTION
+
+Deeply clones a PMC using the visit subsystem.
+
+=cut
+
+*/
+
+enum {
+ state_freezing,
+ state_thawing,
+};
+
+pmclass VisitClone auto_attrs {
+ ATTR INTVAL state; /* state_freezing | state_thawing */
+ ATTR PMC *seen; /* hash mapping seen PMCs to their clones */
+ ATTR PMC *origs; /* de-dupped list of original PMCs */
+ ATTR PMC *clones; /* de-dupped list of clone PMCs */
+
+ /* queues mediating cloning process */
+ ATTR PMC *intval_queue;
+ ATTR PMC *numval_queue;
+ ATTR PMC *string_queue;
+ ATTR PMC *pmc_queue;
+
+/*
+
+=head1 VTABLES
+
+=over 4
+
+=cut
+
+*/
+
+/*
+
+=item C<void init()>
+
+Initializes the PMC.
+
+=cut
+
+*/
+ VTABLE void init() {
+ PObj_custom_mark_SET(SELF);
+
+ PARROT_VISITCLONE(SELF)->seen = Parrot_pmc_new(INTERP, enum_class_Hash);
+ VTABLE_set_pointer(INTERP, PARROT_VISITCLONE(SELF)->seen,
+ parrot_new_pointer_hash(INTERP));
+
+ PARROT_VISITCLONE(SELF)->origs = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+ PARROT_VISITCLONE(SELF)->clones = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+
+ /* TODO: vivify these queues lazily (especially numval_queue) */
+ PARROT_VISITCLONE(SELF)->intval_queue = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
+ PARROT_VISITCLONE(SELF)->numval_queue = Parrot_pmc_new(INTERP, enum_class_ResizableFloatArray);
+ PARROT_VISITCLONE(SELF)->string_queue = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
+ PARROT_VISITCLONE(SELF)->pmc_queue = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+ }
+
+/*
+
+=item C<void mark()>
+
+Mark the PMC as alive.
+
+=cut
+
+*/
+
+ VTABLE void mark() {
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->seen);
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->origs);
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->clones);
+
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->intval_queue);
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->numval_queue);
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->string_queue);
+ Parrot_gc_mark_PMC_alive(interp, PARROT_VISITCLONE(SELF)->pmc_queue);
+ }
+
+/*
+
+=item C<VTABLE PMC *get_iter()>
+
+Get the current list of PMCs to visit.
+
+=cut
+
+*/
+
+ VTABLE PMC *get_iter() {
+ switch (PARROT_VISITCLONE(SELF)->state) {
+ case state_freezing:
+ return PARROT_VISITCLONE(SELF)->origs;
+ case state_thawing:
+ return PARROT_VISITCLONE(SELF)->clones;
+ default:
+ Parrot_ex_throw_from_c_args(INTERP, NULL, 1, "Bad VisitClone.state");
+ }
+ }
+
+/*
+
+=item C<VTABLE INTVAL get_integer()>
+
+Returns the flags describing the current visit action.
+
+=cut
+
+*/
+
+ VTABLE INTVAL get_integer() {
+ switch (PARROT_VISITCLONE(SELF)->state) {
+ case state_freezing:
+ return VISIT_FREEZE_NORMAL;
+ case state_thawing:
+ return VISIT_THAW_NORMAL;
+ default:
+ Parrot_ex_throw_from_c_args(INTERP, NULL, 1, "Bad VisitClone.state");
+ }
+ }
+
+/*
+
+=item C<VTABLE void push_integer(INTVAL v)>
+
+Pushes the integer C<v> into the queue.
+
+=cut
+
+*/
+
+ VTABLE void push_integer(INTVAL v) {
+ VTABLE_push_integer(INTERP, PARROT_VISITCLONE(SELF)->intval_queue, v);
+ }
+
+
+/*
+
+=item C<VTABLE INTVALE shift_integer()>
+
+Shifts an integer of off the queue.
+
+=cut
+
+*/
+
+ VTABLE INTVAL shift_integer() {
+ return VTABLE_shift_integer(INTERP, PARROT_VISITCLONE(SELF)->intval_queue);
+ }
+
+
+/*
+
+=item C<VTABLE void push_float(FLOATVAL v)>
+
+Pushes the float C<v> into the queue.
+
+=cut
+
+*/
+
+ VTABLE void push_float(FLOATVAL v) {
+ VTABLE_push_float(INTERP, PARROT_VISITCLONE(SELF)->numval_queue, v);
+ }
+
+
+/*
+
+=item C<VTABLE FLOATVAL shift_float()>
+
+Shifts a float of off the queue.
+
+=cut
+
+*/
+
+ VTABLE FLOATVAL shift_float() {
+ return VTABLE_shift_float(INTERP, PARROT_VISITCLONE(SELF)->numval_queue);
+ }
+
+
+/*
+
+=item C<VTABLE void push_string(STRING *v)>
+
+Pushes the string C<*v> into the queue.
+
+=cut
+
+*/
+
+ VTABLE void push_string(STRING *v) {
+ VTABLE_push_string(INTERP, PARROT_VISITCLONE(SELF)->string_queue, v);
+ }
+
+
+/*
+
+=item C<VTABLE STRING *shift_string()>
+
+Shifts a string off of the queue.
+
+=cut
+
+*/
+
+ VTABLE STRING *shift_string() {
+ return VTABLE_shift_string(INTERP, PARROT_VISITCLONE(SELF)->string_queue);
+ }
+
+
+/*
+
+=item C<VTABLE void push_pmc(PMC *v)>
+
+Pushes a clone of C<*v> into the queue.
+
+If C<*v> hasn't been seen yet, a clone of it will be made.
+
+=cut
+
+*/
+
+ VTABLE void push_pmc(PMC *orig) {
+ int seen;
+ PMC *clone;
+
+ if (PMC_IS_NULL(orig)) {
+ seen = 1;
+ clone = PMCNULL;
+ }
+ else {
+ Hash *hash = (Hash *)VTABLE_get_pointer(INTERP, PARROT_VISITCLONE(SELF)->seen);
+ HashBucket * const b = parrot_hash_get_bucket(INTERP, hash, orig);
+ if (b) {
+ seen = 1;
+ clone = (PMC *)b->value;
+ }
+ else {
+ seen = 0;
+ clone = Parrot_pmc_new_noinit(INTERP,
+ PObj_is_object_TEST(orig) ? enum_class_Object : orig->vtable->base_type);
+ VTABLE_push_pmc(INTERP, PARROT_VISITCLONE(SELF)->origs, orig);
+ VTABLE_push_pmc(INTERP, PARROT_VISITCLONE(SELF)->clones, clone);
+ parrot_hash_put(INTERP, hash, orig, clone);
+ }
+ }
+
+ VTABLE_push_pmc(INTERP, PARROT_VISITCLONE(SELF)->pmc_queue, clone);
+
+ if (!seen) {
+ /* TODO
+ use separate queues here to minimize size*life of queues?
+ pro: smaller queues
+ con: more GC-ables
+ pro: would simplify shift_pmc() (no more need for seen hash there)
+ */
+ VTABLE_freeze(INTERP, orig, SELF);
+ }
+ }
+
+
+/*
+
+=item C<VTABLE PMC *shift_pmc()>
+
+Shifts a pmc off of the queue.
+
+=cut
+
+*/
+
+ VTABLE PMC *shift_pmc() {
+ PMC *clone = VTABLE_shift_pmc(INTERP, PARROT_VISITCLONE(SELF)->pmc_queue);
+
+ if (!PMC_IS_NULL(clone)) {
+ Hash *hash = (Hash *)VTABLE_get_pointer(INTERP, PARROT_VISITCLONE(SELF)->seen);
+ HashBucket * const b = parrot_hash_get_bucket(INTERP, hash, clone);
+ if (!b) {
+ /* not yet seen */
+ VTABLE_thaw(INTERP, clone, SELF);
+ parrot_hash_put(INTERP, hash, clone, PMCNULL);
+ }
+ }
+
+ return clone;
+ }
+
+/*
+
+=item C<VTABLE PMC *get_pmc()>
+
+Gets the clone PMC.
+
+=cut
+
+*/
+
+ VTABLE PMC *get_pmc() {
+ return VTABLE_get_pmc_keyed_int(INTERP, PARROT_VISITCLONE(SELF)->clones, 0);
+ }
+
+/*
+
+=item C<VTABLE void set_pmc(PMC *p)>
+
+Sets a PMC to be cloned.
+
+=cut
+
+*/
+
+ VTABLE void set_pmc(PMC *p) {
+ /* freeze pmcs to queues */
+ PARROT_VISITCLONE(SELF)->state = state_freezing;
+ VTABLE_push_pmc(INTERP, SELF, p);
+ VTABLE_shift_pmc(INTERP, SELF);
+ Parrot_visit_loop_visit(INTERP, SELF);
+
+ /* drop origs, we don't need it anymore */
+ PARROT_VISITCLONE(SELF)->origs = PMCNULL;
+
+ /* reset seen hash */
+ PARROT_VISITCLONE(SELF)->seen = Parrot_pmc_new(INTERP, enum_class_Hash);
+ VTABLE_set_pointer(INTERP, PARROT_VISITCLONE(SELF)->seen,
+ parrot_new_pointer_hash(INTERP));
+
+ /* thaw clones from queues */
+ PARROT_VISITCLONE(SELF)->state = state_thawing;
+ Parrot_visit_loop_visit(INTERP, SELF);
+ Parrot_visit_loop_thawfinish(INTERP, SELF);
+ }
+
+/*
+
+=back
+
+=cut
+
+*/
+
+}
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
Modified: branches/tt1015/src/pmc_freeze.c
==============================================================================
--- branches/tt1015/src/pmc_freeze.c Mon Mar 8 11:08:50 2010 (r44755)
+++ branches/tt1015/src/pmc_freeze.c Mon Mar 8 15:08:13 2010 (r44756)
@@ -185,7 +185,19 @@
Parrot_clone(PARROT_INTERP, ARGIN(PMC *pmc))
{
ASSERT_ARGS(Parrot_clone)
- return VTABLE_clone(interp, pmc);
+
+ PMC *cloner, *result;
+
+ cloner = Parrot_pmc_new(interp, enum_class_VisitClone);
+ VTABLE_set_pmc(interp, cloner, pmc);
+ result = VTABLE_get_pmc(interp, cloner);
+
+ return result;
+
+ /* equivalent but wasteful code:
+ STRING *img = Parrot_freeze(interp, pmc);
+ return Parrot_thaw(interp, img);
+ */
}
/*
More information about the parrot-commits
mailing list