[svn:parrot] r47352 - in branches/gsoc_instrument: examples/library runtime/parrot/library/Instrument src/dynpmc
khairul at svn.parrot.org
khairul at svn.parrot.org
Fri Jun 4 12:36:58 UTC 2010
Author: khairul
Date: Fri Jun 4 12:36:57 2010
New Revision: 47352
URL: https://trac.parrot.org/parrot/changeset/47352
Log:
Reworked the data structures for the hooks, use a linked list now instead.
Modified:
branches/gsoc_instrument/examples/library/tracer.nqp
branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp
branches/gsoc_instrument/src/dynpmc/instrument.pmc
Modified: branches/gsoc_instrument/examples/library/tracer.nqp
==============================================================================
--- branches/gsoc_instrument/examples/library/tracer.nqp Fri Jun 4 12:33:52 2010 (r47351)
+++ branches/gsoc_instrument/examples/library/tracer.nqp Fri Jun 4 12:36:57 2010 (r47352)
@@ -59,12 +59,9 @@
# Constant keys are int constants or strings.
if pir::band__III($arg_type, 2) == 2 {
# String constant key.
- #my $arg := $instr_obj.get_op_arg($op[$cur_arg + 1], $arg_type);
- # TODO: For pir code below, the above blows up. Figure out why.
- # current workaround is to just print out the PMC constant value.
- # $S0 = "test"
- # $P1[$S0] = "sth"
- $arg_str := '[' ~ 'PC' ~ $op[$cur_arg + 1] ~ ']';
+ my $arg := $instr_obj.get_op_arg($op[$cur_arg + 1], $arg_type);
+ $arg_str := '["' ~ $arg ~ '"]';
+
} else {
# Integer constant key.
$arg_str := '[' ~ $op[$cur_arg + 1] ~ ']';
@@ -90,6 +87,7 @@
if pir::band__III($arg_type, 1) == 1 {
$arg_str := '"' ~ $arg ~ '"';
+
} else {
$arg_str := $arg;
}
Modified: branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp
==============================================================================
--- branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp Fri Jun 4 12:33:52 2010 (r47351)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp Fri Jun 4 12:36:57 2010 (r47352)
@@ -201,11 +201,11 @@
if $!is_enabled {
if $!is_catchall {
# Attach a catchall hook.
- $!instr_obj.remove_op_catchall($!identifier);
+ $!instr_obj.remove_op_catchall($!identifier, $!callback);
} else {
# Attach a hook to each op in @!oplist.
for $!oplist {
- $!instr_obj.remove_op_hook($!identifier, $_);
+ $!instr_obj.remove_op_hook($!identifier, $_, $!callback);
}
}
Modified: branches/gsoc_instrument/src/dynpmc/instrument.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrument.pmc Fri Jun 4 12:33:52 2010 (r47351)
+++ branches/gsoc_instrument/src/dynpmc/instrument.pmc Fri Jun 4 12:36:57 2010 (r47352)
@@ -25,9 +25,23 @@
#include "parrot/embed.h"
/*
+ * Structures for the linked list data type.
+ */
+
+typedef struct probe_node_t {
+ struct probe_node_t *next, *prev;
+ PMC *list_obj;
+} probe_node_t;
+
+typedef struct probe_list_t {
+ probe_node_t *head, *tail;
+} probe_list_t;
+
+/*
* Extend the runcore_t struct to include a reference
* to the supervisor interpreter.
*/
+
typedef struct Instrument_runcore_t {
STRING *name;
int id;
@@ -38,29 +52,31 @@
INTVAL flags;
/* End of common members */
- PMC *supervisor;
+ Parrot_Interp supervisor_interp;
+ PMC *supervisor_pmc;
+ probe_list_t **op_hooks;
+ probe_list_t *op_catchall;
} Instrument_runcore_t;
-/* Define the enumeration for op lookups */
-typedef enum {
- OP_LOOKUP = 0,
- OP_INFO = 1,
- OP_FULLNAME = 2,
- OP_NAME = 3,
- OP_ARGS = 4,
- OP_COUNT = 5
-} Instrument_op_query_t;
-
/* Runcore Function Prototypes */
-static void Instrument_runcore_init (PARROT_INTERP, PMC *supervisor);
-static opcode_t * Instrument_runcore_runops(PARROT_INTERP, Parrot_runcore_t *runcore, opcode_t *pc);
+static void Instrument_runcore_init (PARROT_INTERP, Parrot_Interp supervisor, PMC *instrument);
+static opcode_t *Instrument_runcore_runops (PARROT_INTERP, Parrot_runcore_t *runcore, opcode_t *pc);
+static void Instrument_init_probes (Parrot_Interp supervisor, Parrot_Interp supervised);
+
+/* Helper prototype */
+static opcode_t *Instrument_fire_hooks (opcode_t *pc, PARROT_INTERP);
+
+/* Linked List operations */
+static probe_list_t *probe_list_create_list (PARROT_INTERP);
+static probe_node_t *probe_list_create_node (PARROT_INTERP);
+static void probe_list_delete_node (PARROT_INTERP, probe_node_t *node);
+static void probe_list_push (PARROT_INTERP, probe_list_t *list, PMC *item);
+static PMC *probe_list_pop (PARROT_INTERP, probe_list_t *list);
+static PMC *probe_list_remove (PARROT_INTERP, probe_list_t *list, probe_node_t *node);
+static probe_node_t *probe_list_find (PARROT_INTERP, probe_list_t *list, PMC *val);
pmclass Instrument auto_attrs dynpmc provides hash {
- ATTR Parrot_Interp supervisor; /* The interpreter that created this instance */
ATTR Parrot_Interp supervised; /* The interpreter running the code */
- ATTR opcode_t *cur_pc;
- ATTR PMC *op_hooks; /* A ResizablePMCArray for holding references to op hooks */
- ATTR PMC *op_catchall; /* These callbacks are to be called on each op */
ATTR PMC *probes; /* A list of probes registered. */
/*
@@ -74,18 +90,21 @@
*/
VTABLE void init () {
- struct parrot_interp_t *in;
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
/* Create the child interpreter PMC */
- attr->supervisor = INTERP;
- attr->supervised = Parrot_new(attr->supervisor);
- attr->op_hooks = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
- attr->op_catchall = Parrot_pmc_new(INTERP, enum_class_Hash);
+ attr->supervised = Parrot_new(INTERP);
attr->probes = Parrot_pmc_new(INTERP, enum_class_Hash);
/* Initialize the runcore for the child interpreter */
- Instrument_runcore_init(attr->supervised, SELF);
+ Instrument_runcore_init(attr->supervised, INTERP, SELF);
+
+ /* Initialize the scheduler for the child interpreter */
+ attr->supervised->scheduler = Parrot_pmc_new(interp, enum_class_Scheduler);
+ attr->supervised->scheduler = VTABLE_share_ro(interp, attr->supervised->scheduler);
+
+ /* Prepare the child interpreter's op table for instrumentation */
+ Instrument_init_probes(INTERP, attr->supervised);
/* Set self to destroy manually */
PObj_custom_mark_destroy_SETALL(SELF);
@@ -104,16 +123,10 @@
VTABLE void destroy () {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ /* TODO: Delete the linked list entries. */
+
/* Delete the supervised interpreter */
Parrot_destroy(attr->supervised);
-
- /* Set the references to null */
- /* TODO: Is there a better way to delete them? */
- attr->supervisor = NULL;
- attr->supervised = NULL;
- attr->op_hooks = NULL;
- attr->op_catchall = NULL;
- attr->probes = NULL;
}
/*
@@ -128,95 +141,13 @@
VTABLE void mark () {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
-
+
/* Mark attributes as alive */
- Parrot_gc_mark_PMC_alive_fun(INTERP, attr->op_hooks);
- Parrot_gc_mark_PMC_alive_fun(INTERP, attr->op_catchall);
Parrot_gc_mark_PMC_alive_fun(INTERP, attr->probes);
}
/*
-=item C<void * get_pointer()>
-
-Returns a reference to the supervising interpreter,
-meaning the interpreter that runs the instruments.
-
-=cut
-
-*/
-
- VTABLE void * get_pointer () {
- Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
- return attr->supervisor;
- }
-
-/*
-
-=item C<void set_pointer(void *pc_pointer)>
-
-With the pc_pointer passed in, execute the current op at
-the given address after firing all hooks that apply.
-
-=cut
-
-*/
-
- VTABLE void set_pointer (void *pc_pointer) {
- opcode_t *pc = (opcode_t *) pc_pointer;
- PMC *hooks, *hook_iter, *catchall_iter, *op_data;
- Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
- INTVAL pc_relative, cur_op_param, op_params;
-
- attr->cur_pc = pc;
-
- /* Calculate the relative position of the pc. */
- pc_relative = pc - attr->supervised->code->base.data;
-
- /* Grab the opcode params */
- op_params = attr->supervised->op_info_table[*pc].op_count;
- op_data = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
- cur_op_param = 0;
- while(cur_op_param <= op_params) {
- VTABLE_push_integer(INTERP, op_data, pc[cur_op_param]);
- cur_op_param++;
- }
-
- /* Fire the catchall hooks first */
- catchall_iter = VTABLE_get_iter(INTERP, attr->op_catchall);
- while(VTABLE_get_bool(INTERP, catchall_iter)) {
- PMC *val, *key;
-
- key = VTABLE_shift_pmc(INTERP, catchall_iter);
- val = VTABLE_get_pmc_keyed(INTERP, attr->op_catchall, key);
-
- if(!PMC_IS_NULL(val)) {
- Parrot_ext_call(INTERP, val, "IPP->", pc_relative, op_data, SELF);
- }
- }
-
- /* Fire the specific probes */
- hooks = VTABLE_get_pmc_keyed_int(INTERP, attr->op_hooks, *pc);
- if(!PMC_IS_NULL(hooks)) {
- hook_iter = VTABLE_get_iter(INTERP, hooks);
- while(VTABLE_get_bool(INTERP, hook_iter)) {
- PMC *val, *key;
-
- key = VTABLE_shift_pmc(INTERP, hook_iter);
- val = VTABLE_get_pmc_keyed(INTERP, hooks, key);
-
- if(!PMC_IS_NULL(val)) {
- Parrot_ext_call(INTERP, val, "IPP->", pc_relative, op_data, SELF);
- }
- }
- }
-
- /* Done firing hooks */
- return;
- }
-
-/*
-
=item C<void get_pmc_keyed(PMC *key)>
Get the property with the key.
@@ -274,12 +205,7 @@
if(!Parrot_pmc_is_null(INTERP, args)
&& VTABLE_type(INTERP, args) == enum_class_ResizableStringArray
&& VTABLE_get_integer(INTERP, args) > 0) {
- /* There are some arguments to be passed to
- the child interpreter. We need to convert
- them from Parrot strings to c-strings so
- that we can pass it to imcc.
- */
-
+
/* Get the number of argument values */
int count = VTABLE_get_integer(INTERP, args);
@@ -299,10 +225,11 @@
status = imcc_run(attr->supervised,
Parrot_str_cstring(attr->supervised, file),
argc, (const char **) argv);
- if (status)
+ if (status) {
imcc_run_pbc(attr->supervised,
attr->supervised->output_file,
argc,(const char **) argv);
+ }
/* Finalize the instruments */
probe_iter = VTABLE_get_iter(INTERP, attr->probes);
@@ -374,7 +301,7 @@
/* Call the method.
The first parameter to a method is the object itself.
- The enable method will be calling insert_hooks(HASH) to register the hooks. */
+ The enable method will be calling insert_op_hook to register the hooks. */
Parrot_ext_call(INTERP, enable_method, "P->", obj);
/* Register the probe. */
@@ -393,16 +320,15 @@
*/
METHOD insert_op_hook (PMC *id, INTVAL op_num, PMC *hook) {
- PMC *op_num_hooks;
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+ probe_list_t **list = core->op_hooks;
- op_num_hooks = VTABLE_get_pmc_keyed_int(INTERP, attr->op_hooks, op_num);
- if(PMC_IS_NULL(op_num_hooks)) {
- op_num_hooks = Parrot_pmc_new(INTERP, enum_class_Hash);
- VTABLE_set_pmc_keyed_int(INTERP, attr->op_hooks, op_num, op_num_hooks);
+ if(list[op_num] == NULL) {
+ list[op_num] = probe_list_create_list(INTERP);
}
- VTABLE_set_pmc_keyed(INTERP, op_num_hooks, id, hook);
+ probe_list_push(INTERP, list[op_num], hook);
}
/*
@@ -415,13 +341,18 @@
*/
- METHOD remove_op_hook (PMC *id, INTVAL op_num) {
- PMC *op_num_hooks;
+ METHOD remove_op_hook (PMC *id, INTVAL op_num, PMC *callback) {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+ probe_list_t **list = core->op_hooks;
+ probe_node_t *node = NULL;
- op_num_hooks = VTABLE_get_pmc_keyed_int(INTERP, attr->op_hooks, op_num);
- if(!PMC_IS_NULL(op_num_hooks)) {
- VTABLE_delete_keyed(INTERP, op_num_hooks, id);
+ if(list[op_num] != NULL) {
+ node = probe_list_find(INTERP, list[op_num], callback);
+
+ if(node != NULL) {
+ probe_list_remove(INTERP, list[op_num], node);
+ }
}
}
@@ -435,8 +366,10 @@
METHOD insert_op_catchall (PMC *id, PMC *callback) {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+ probe_list_t *list = core->op_catchall;
- VTABLE_set_pmc_keyed(INTERP, attr->op_catchall, id, callback);
+ probe_list_push(INTERP, list, callback);
}
/*
@@ -447,10 +380,15 @@
=cut
*/
- METHOD remove_op_catchall (PMC *id) {
+ METHOD remove_op_catchall (PMC *id, PMC *callback) {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+ probe_list_t *list = core->op_catchall;
+ probe_node_t *node = NULL;
- VTABLE_delete_keyed(INTERP, attr->op_catchall, id);
+ node = probe_list_find(INTERP, list, callback);
+
+ probe_list_remove(INTERP, list, node);
}
/*
@@ -468,7 +406,7 @@
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
PMC *ret, *cc, *key;
arg_type_t type = (arg_type_t) arg_type;
-
+
cc = CURRENT_CONTEXT(attr->supervised);
switch(type) {
@@ -544,12 +482,6 @@
RETURN(PMC *ret);
}
- METHOD get_key_value (PMC *key) {
- Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
- STRING *key_str = key_string(attr->supervised, key);
- RETURN(STRING *key_str);
- }
-
}
/*
@@ -560,60 +492,279 @@
* This is the simplified custom runops function.
* This is based on the PARROT_FAST_RUNCORE.
*/
+
static
opcode_t *
Instrument_runcore_runops(PARROT_INTERP, Parrot_runcore_t *runcore, opcode_t *pc)
-{
+{
Instrument_runcore_t *core = (Instrument_runcore_t *) runcore;
-
- PMC *pmc = core->supervisor;
- Parrot_Interp supervisor = (Parrot_Interp) VTABLE_get_pointer(interp, pmc);
+ Parrot_Interp supervisor = core->supervisor_interp;
while (pc) {
- Parrot_pcc_set_pc(interp, CURRENT_CONTEXT(interp), pc);
-
- /* Fire the hooks */
- VTABLE_set_pointer(supervisor, pmc, pc);
-
+ Parrot_pcc_set_pc(interp, CURRENT_CONTEXT(interp), pc);
+
+ /* TODO: This is a hack to get around dynops for now.
+ Since dynops are loaded by the child interpreter
+ and there is no easy way to get notification of that,
+ this will do for now.
+ */
+ if(supervisor->op_func_table != interp->op_func_table) {
+ Instrument_init_probes(supervisor, interp);
+
+ supervisor->op_lib = interp->op_lib;
+ supervisor->op_count = interp->op_count;
+ supervisor->op_func_table = interp->op_func_table;
+ supervisor->op_info_table = interp->op_info_table;
+ }
+
+ Instrument_fire_hooks(pc, interp);
DO_OP(pc, interp);
+
+ /* Force events */
+ Parrot_cx_handle_tasks(interp, interp->scheduler);
}
-
+
return pc;
-
+
}
/*
* This is the initializer for the runcore.
* Sets up runcore_t.
*/
+
static
void
-Instrument_runcore_init (PARROT_INTERP, PMC *supervisor) {
- Instrument_runcore_t * const coredata =
- mem_gc_allocate_zeroed_typed(interp, Instrument_runcore_t);
-
- /* Ensure the current loaded runcore is the slow core */
- Parrot_set_run_core(interp, PARROT_SLOW_CORE);
-
- /* Copy the runcore entry for the PARROT_SLOW_CORE,
- and then make modifications to it.
- Copy so that we get the opinit function pointer.
- */
- mem_copy_n_typed(coredata, interp->run_core, 1, Parrot_runcore_t);
-
- coredata->name = string_from_literal(interp, "instrument");
- coredata->runops = Instrument_runcore_runops;
- coredata->prepare_run = NULL;
- coredata->destroy = NULL;
- coredata->flags = 0;
- coredata->supervisor = supervisor;
-
- PARROT_RUNCORE_FUNC_TABLE_SET((Parrot_runcore_t *)coredata);
-
- Parrot_runcore_register(interp, (Parrot_runcore_t *) coredata);
-
- //Switch to this runcore.
- Parrot_runcore_switch(interp, coredata->name);
+Instrument_runcore_init (PARROT_INTERP, Parrot_Interp supervisor, PMC *instrument) {
+ Instrument_runcore_t * const coredata =
+ mem_gc_allocate_zeroed_typed(interp, Instrument_runcore_t);
+
+ /* Ensure the current loaded runcore is the slow core */
+ Parrot_set_run_core(interp, PARROT_SLOW_CORE);
+
+ /* Copy the runcore entry for the PARROT_SLOW_CORE,
+ and then make modifications to it.
+ Copy so that we get the opinit function pointer.
+ */
+ mem_copy_n_typed(coredata, interp->run_core, 1, Parrot_runcore_t);
+
+ coredata->name = string_from_literal(interp, "instrument");
+ coredata->runops = Instrument_runcore_runops;
+ coredata->prepare_run = NULL;
+ coredata->destroy = NULL;
+ coredata->flags = 0;
+ coredata->supervisor_interp = supervisor;
+ coredata->supervisor_pmc = instrument;
+ coredata->op_hooks = NULL;
+ coredata->op_catchall = NULL;
+
+ PARROT_RUNCORE_FUNC_TABLE_SET((Parrot_runcore_t *)coredata);
+
+ Parrot_runcore_register(interp, (Parrot_runcore_t *) coredata);
+
+ //Switch to this runcore.
+ Parrot_runcore_switch(interp, coredata->name);
+}
+
+/*
+ * This is the initializer for the probe tables.
+ * Probes are stored in the extended runcore_t.
+ */
+
+static void Instrument_init_probes (Parrot_Interp supervisor, Parrot_Interp supervised) {
+ Instrument_runcore_t *core;
+ INTVAL op_count;
+
+ core = (Instrument_runcore_t *) supervised->run_core;
+ op_count = supervised->op_count;
+
+ /* Create the probe list table */
+ if(!core->op_hooks) {
+ /* First time allocating. */
+ core->op_hooks = mem_gc_allocate_n_zeroed_typed(supervisor, op_count, probe_list_t *);
+ core->op_catchall = probe_list_create_list(supervisor);
+
+ } else {
+ /* Reallocate. */
+ INTVAL old_count = supervisor->op_count;
+ core->op_hooks = mem_gc_realloc_n_typed_zeroed(supervisor, core->op_hooks,
+ op_count, old_count, probe_list_t *);
+ }
+}
+
+/*
+ * This will fire the probes.
+ */
+
+static opcode_t *Instrument_fire_hooks (opcode_t *pc, PARROT_INTERP) {
+ /* If this stub is called, this op is instrumented. */
+ probe_list_t *to_recall, *op_probes, *op_catchalls;
+ probe_node_t *cur_probe;
+ Instrument_runcore_t *core;
+ Parrot_Interp supervisor;
+ PMC *instrument, *op_data;
+ INTVAL op_params, cur_op_param, pc_relative, done_catchalls;
+
+ core = (Instrument_runcore_t *) interp->run_core;
+ to_recall = NULL; /* TODO: Implement probe recalls */
+ op_probes = core->op_hooks[*pc];
+ op_catchalls = core->op_catchall;
+ supervisor = core->supervisor_interp;
+ instrument = core->supervisor_pmc;
+
+ /* Calculate the relative position of the pc. */
+ pc_relative = pc - interp->code->base.data;
+
+ /* Grab the opcode params */
+ /* TODO: Apparently some ops like set_args_pc have extra args.
+ see src/runcore/trace.c line 312.
+ */
+ op_params = interp->op_info_table[*pc].op_count;
+ op_data = Parrot_pmc_new(supervisor, enum_class_ResizableIntegerArray);
+ cur_op_param = 0;
+ while(cur_op_param <= op_params) {
+ VTABLE_push_integer(supervisor, op_data, pc[cur_op_param]);
+ cur_op_param++;
+ }
+
+ /* Execute any probes. */
+ done_catchalls = 0;
+ cur_probe = (op_catchalls != NULL) ? op_catchalls->head : NULL;
+ while(cur_probe != NULL || !done_catchalls) {
+ PMC *callback;
+
+ /* Switch to the specific probes if we are done with catchalls. */
+ if(cur_probe == NULL && !done_catchalls) {
+ cur_probe = (op_probes != NULL) ? op_probes->head : NULL;
+ done_catchalls = 1;
+ continue;
+ }
+
+ /* Fire the probe. */
+ callback = cur_probe->list_obj;
+
+ if(!PMC_IS_NULL(callback)) {
+ Parrot_ext_call(supervisor, callback, "IPP->", pc_relative, op_data, instrument);
+ }
+
+ cur_probe = cur_probe->next;
+ }
+
+ /* Done */
+ return pc;
+}
+
+/*
+ * Functions implementing the linked list for the probes.
+ */
+
+/*
+ * Creates a new list.
+ */
+static probe_list_t *probe_list_create_list (PARROT_INTERP) {
+ probe_list_t *list;
+
+ list = mem_gc_allocate_zeroed_typed(interp, probe_list_t);
+
+ list->head = list->tail = NULL;
+
+ return list;
+}
+
+/*
+ * Creates a new list node.
+ */
+static probe_node_t *probe_list_create_node (PARROT_INTERP) {
+ probe_node_t *node;
+
+ node = mem_gc_allocate_zeroed_typed(interp, probe_node_t);
+
+ node->next = NULL;
+ node->prev = NULL;
+ node->list_obj = NULL;
+
+ return node;
+}
+
+/*
+ * Deletes the node.
+ */
+static void probe_list_delete_node (PARROT_INTERP, probe_node_t *node) {
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+
+ node->next = node->prev = NULL;
+
+ mem_gc_free(interp, node);
+}
+
+/*
+ * Pushes item to the end of the list.
+ */
+static void probe_list_push (PARROT_INTERP, probe_list_t *list, PMC *item) {
+ probe_node_t *node = probe_list_create_node(interp);
+ node->list_obj = item;
+
+ if(list->head == NULL) {
+ list->head = list->tail = node;
+ } else {
+ node->prev = list->tail;
+ node->next = NULL;
+ list->tail->next = node;
+ list->tail = node;
+ }
+}
+
+/*
+ * Removes item at the end of the list.
+ */
+static PMC * probe_list_pop (PARROT_INTERP, probe_list_t *list) {
+ PMC *item = PMCNULL;
+ probe_node_t *node = list->tail;
+
+ if(node != NULL) {
+ if(node == list->head) {
+ list->head = list->tail = NULL;
+ } else {
+ list->tail = node->prev;
+ list->tail->next = NULL;
+ }
+
+ item = node->list_obj;
+
+ probe_list_delete_node(interp, node);
+ }
+
+ return item;
+}
+
+/*
+ * Removes the given node. Used with probe_list_find.
+ * Returns the item in that node.
+ */
+static PMC * probe_list_remove (PARROT_INTERP, probe_list_t *list, probe_node_t *node) {
+ PMC *item;
+
+ item = node->list_obj;
+
+ probe_list_delete_node(interp, node);
+
+ return item;
+}
+
+/*
+ * Locates item within the list and returns the node.
+ */
+static probe_node_t *probe_list_find (PARROT_INTERP, probe_list_t *list, PMC *val) {
+ probe_node_t *cur_node = list->head;
+
+ while(cur_node != NULL) {
+ if(cur_node->list_obj == val) { return cur_node; }
+
+ cur_node = cur_node->next;
+ }
+
+ return NULL;
}
/*
More information about the parrot-commits
mailing list