[svn:parrot] r48111 - in branches/gsoc_instrument: runtime/parrot/library/Instrument src/dynpmc
khairul at svn.parrot.org
khairul at svn.parrot.org
Mon Jul 19 16:38:23 UTC 2010
Author: khairul
Date: Mon Jul 19 16:38:22 2010
New Revision: 48111
URL: https://trac.parrot.org/parrot/changeset/48111
Log:
Add NULL check when destroying InstrumentVtable.
Modified:
branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp
branches/gsoc_instrument/src/dynpmc/instrument.pmc
branches/gsoc_instrument/src/dynpmc/instrumentgc.pmc
branches/gsoc_instrument/src/dynpmc/instrumentvtable.pmc
Modified: branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp
==============================================================================
--- branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp Mon Jul 19 09:38:32 2010 (r48110)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp Mon Jul 19 16:38:22 2010 (r48111)
@@ -225,6 +225,7 @@
};
for (@!class_names) {
+
my $class_name := $_;
my $class := $!instr_obj.instrument_class($class_name);
my $event_prefix := 'Class::' ~ $class_name ~ '::';
@@ -256,26 +257,30 @@
sub setup_load_event($instrument) {
if !pir::defined__IP($Instrument::Event::Class::loadlib_event) {
- # Get the callback.
- my $callback := pir::get_global__PS("load_cb");
-
# Define the loadlib event for this class.
my $loadlib := Instrument::Event::Internal::loadlib.new();
- $loadlib.callback($callback);
+ $loadlib.callback(pir::get_global__PS("load_cb"));
$instrument.attach($loadlib);
$Instrument::Event::Class::loadlib_event := $loadlib;
# Define the load_bytecode event for this class.
my $bytecode := Instrument::Probe.new();
$bytecode.inspect('load_bytecode');
- $bytecode.callback($callback);
+ $bytecode.callback(pir::get_global__PS("loadbytecode_cb"));
$instrument.attach($bytecode);
$Instrument::Event::Class::loadbytecode_event := $bytecode;
}
};
- sub load_cb($arg1?, $arg2?, $arg3?) {
- say('Load event!');
+ sub load_cb($data) {
+ reload_todos();
+ }
+
+ sub loadbytecode_cb($op, $instr, $probe) {
+ return pir::get_global__PS('reload_todos');
+ }
+
+ sub reload_todos() {
my @list := @Instrument::Event::Class::todo;
@Instrument::Event::Class::todo := ();
Modified: branches/gsoc_instrument/src/dynpmc/instrument.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrument.pmc Mon Jul 19 09:38:32 2010 (r48110)
+++ branches/gsoc_instrument/src/dynpmc/instrument.pmc Mon Jul 19 16:38:22 2010 (r48111)
@@ -69,11 +69,12 @@
static void Instrument_init_probes(Parrot_Interp supervisor, Parrot_Interp supervised);
/* Helper prototype */
-static opcode_t *Instrument_fire_hooks(opcode_t *pc, PARROT_INTERP);
-static void raise_dynlib_event(PARROT_INTERP, PMC *lib);
+static probe_list_t *Instrument_get_active_probes(opcode_t *pc, PARROT_INTERP);
+static probe_list_t *Instrument_fire_probes(probe_list_t *list, opcode_t *pc, PARROT_INTERP);
+static void raise_dynlib_event(PARROT_INTERP, PMC *lib);
/* dynlib detection */
-static void normalise_vtables(Parrot_Interp src, Parrot_Interp dest);
+static void fixup_vtables(Parrot_Interp src, Parrot_Interp dest);
static void normalise_op_tables(Parrot_Interp src, Parrot_Interp dest);
static void detect_loadlib(PARROT_INTERP);
@@ -88,10 +89,11 @@
static probe_node_t *probe_list_find(PARROT_INTERP, probe_list_t *list, PMC *val);
pmclass Instrument auto_attrs dynpmc provides hash group instrument_group {
- ATTR Parrot_Interp supervised; /* The interpreter running the code */
- ATTR PMC *probes; /* A list of probes registered. */
- ATTR PMC *evt_dispatcher;
- ATTR PMC *instrument_gc;
+ ATTR Parrot_Interp supervised; /* The interpreter running the code */
+ ATTR PMC *probes; /* A list of probes registered. */
+ ATTR PMC *evt_dispatcher; /* Reference the the EventDispatcher object. */
+ ATTR PMC *instrument_gc; /* Reference to the InstrumentGC object. */
+ ATTR PMC *instrument_classes; /* Registry to hold instances of InstrumentVtable. */
/*
@@ -119,9 +121,10 @@
gc_class_type = Parrot_pmc_get_type_str(INTERP, CONST_STRING(INTERP, "InstrumentGC"));
/* Initialise the attributes. */
- attr->supervised = Parrot_new(INTERP);
- attr->probes = Parrot_pmc_new(INTERP, enum_class_Hash);
- attr->evt_dispatcher = Parrot_pmc_new(INTERP, evt_class_type);
+ attr->supervised = Parrot_new(INTERP);
+ attr->probes = Parrot_pmc_new(INTERP, enum_class_Hash);
+ attr->evt_dispatcher = Parrot_pmc_new(INTERP, evt_class_type);
+ attr->instrument_classes = Parrot_pmc_new(INTERP, enum_class_Hash);
/* Initialise the event dispatcher */
(PMC *nothing) = PCCINVOKE(INTERP, attr->evt_dispatcher, "_self_init");
@@ -199,6 +202,7 @@
Parrot_gc_mark_PMC_alive_fun(INTERP, attr->instrument_gc);
Parrot_gc_mark_PMC_alive_fun(INTERP, core->old_dynlibs);
Parrot_gc_mark_PMC_alive_fun(INTERP, core->instr_op);
+ Parrot_gc_mark_PMC_alive_fun(INTERP, attr->instrument_classes);
}
/*
@@ -253,14 +257,15 @@
=item C<void run(STRING file, PMC *args)>
-Loads the given file and run it with the args given.
+Executes the given file, 'file', in the child interpreter,
+passing the arguments in the form of the array 'args' to the
+program in 'file'.
=cut
*/
METHOD run(STRING file, PMC *args) {
- PMC *entry_point;
int argc = 0, status;
char * default_argv[] = {NULL};
char ** argv = default_argv;
@@ -269,12 +274,12 @@
PMC *probe_iter;
int counter = 0;
- /* If args is not null, is of type ResizableStringArray and has at
- least 1 element, process it so we can pass it to the child interpreter.
+ /* If args is not null, does array and has a size > 0, convert it
+ into a cstring array to pass to imcc.
*/
if (!Parrot_pmc_is_null(INTERP, args)
- && VTABLE_type(INTERP, args) == enum_class_ResizableStringArray
- && VTABLE_get_integer(INTERP, args) > 0) {
+ && VTABLE_does(INTERP, args, CONST_STRING(INTERP, "array"))
+ && VTABLE_get_integer(INTERP, args) > 0) {
/* Get the number of argument values */
int count = VTABLE_get_integer(INTERP, args);
@@ -291,8 +296,8 @@
}
}
- /* Normalise the vtables */
- normalise_vtables(INTERP, attr->supervised);
+ /* Fixup the vtables */
+ fixup_vtables(INTERP, attr->supervised);
/* Begin Execution */
file_c = Parrot_str_to_cstring(attr->supervised, file);
@@ -341,7 +346,7 @@
=item C<void attach(PMC *obj)>
With the passed in object, assume it is a class with the method 'enable'
-and attribute 'instr_obj'. Set the 'instr_obj' to SELF and call the
+and attribute 'instr_obj'. Set the '$!instr_obj' attribute to SELF and call the
'enable' method of the object for the object to commence attaching the hooks.
=cut
@@ -450,7 +455,7 @@
/*
=item C<INTVAL count_op_hooks(INTVAL op_num)>
-Returns the number of enabled op catchall probes.
+Returns the number of enabled op hooks for the given op number.
=cut
*/
@@ -538,15 +543,33 @@
RETURN(INTVAL count);
}
+/*
+=item C<PMC* instrument_class(STRING *classname)>
+
+Returns the InstrumentVtable instance associated with the given classname.
+Creates a new InstrumentVtable instance if there is none currently associated.
+
+=cut
+*/
METHOD instrument_class(STRING *classname) {
- INTVAL class_type;
- PMC *class_instr;
+ Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ INTVAL class_type;
+ PMC *class_instr;
- class_type = Parrot_pmc_get_type_str(INTERP, CONST_STRING(INTERP, "InstrumentVtable"));
- class_instr = Parrot_pmc_new_init(INTERP, class_type, SELF);
+ /* Lookup the classname in the InstrumentClass registry.
+ If the entry doesn't exist, create an entry for it. */
+ if (VTABLE_exists_keyed_str(INTERP, attr->instrument_classes, classname)) {
+ class_instr = VTABLE_get_pmc_keyed_str(INTERP, attr->instrument_classes, classname);
+ }
+ else {
+ class_type = Parrot_pmc_get_type_str(INTERP, CONST_STRING(INTERP, "InstrumentVtable"));
+ class_instr = Parrot_pmc_new_init(INTERP, class_type, SELF);
- () = PCCINVOKE(INTERP, class_instr, "attach_to_class", STRING *classname);
+ () = PCCINVOKE(INTERP, class_instr, "attach_to_class", STRING *classname);
+
+ VTABLE_set_pmc_keyed_str(INTERP, attr->instrument_classes, classname, class_instr);
+ }
RETURN(PMC *class_instr);
}
@@ -603,11 +626,16 @@
Parrot_ex_add_c_handler(interp, &exc_handler);
while (pc && !(core->has_ended)) {
+ probe_list_t *callbacks, *recalls, *ignore;
opcode_t *pc_copy = pc;
Parrot_pcc_set_pc(interp, CURRENT_CONTEXT(interp), pc);
- Instrument_fire_hooks(pc, interp);
+ /* Get the list of callbacks to call and execute the op. */
+ callbacks = Instrument_get_active_probes(pc, interp);
+ recalls = Instrument_fire_probes(callbacks, pc, interp);
DO_OP(pc, interp);
+ ignore = Instrument_fire_probes(recalls, pc_copy, interp);
+ probe_list_delete_list(supervisor, ignore);
/* Todo: Move this to a probe. This detects loadlib opcodes. */
if (*pc_copy == enum_ops_loadlib_p_s
@@ -704,58 +732,109 @@
}
/*
- * This will fire the probes.
+ * Returns a list of Probe objects to be called by Instrument_fire_probes.
+ */
+
+static probe_list_t * Instrument_get_active_probes(opcode_t *pc, PARROT_INTERP) {
+ probe_list_t *list;
+ probe_node_t *cur_node;
+ Instrument_runcore_t *core;
+ Parrot_Interp supervisor;
+
+ core = (Instrument_runcore_t *) interp->run_core;
+ supervisor = core->supervisor_interp;
+ list = probe_list_create_list(supervisor);
+
+ /* Copy over the list entries for the catchalls
+ and specific op probes into the list. */
+ cur_node = core->op_catchall->head;
+ while (cur_node != NULL) {
+ probe_list_push(supervisor, list, cur_node->list_obj);
+ cur_node = cur_node->next;
+ }
+
+ if (core->op_hooks[*pc] != NULL) {
+ cur_node = core->op_hooks[*pc]->head;
+ while (cur_node != NULL) {
+ probe_list_push(supervisor, list, cur_node->list_obj);
+ cur_node = cur_node->next;
+ }
+ }
+
+ return list;
+}
+
+/*
+ * Executes the hooks given in the list 'list'.
+ * Each entry in this list can either be the Probe object or a RPA that
+ * has 2 elements, the Probe object and an invokable.
+ * If the invokable returns a PMC that is also invokable, this return
+ * value then goes into the recall list to be called after the op is executed.
*/
-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 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;
+static probe_list_t * Instrument_fire_probes(probe_list_t *list, opcode_t *pc, PARROT_INTERP) {
+ Parrot_Interp supervisor;
+ PMC *instrument, *op_data;
+ Instrument_runcore_t *core;
+ probe_node_t *cur_probe;
+ probe_list_t *recall_list;
+
+ core = (Instrument_runcore_t *) interp->run_core;
+ supervisor = core->supervisor_interp;
+ instrument = core->supervisor_pmc;
+ op_data = core->instr_op;
+ recall_list = probe_list_create_list(supervisor);
- /* Update the pc of the InstrumentOp object. */
- op_data = core->instr_op;
+ /* Update pc of InstrumentOp object. */
VTABLE_set_pointer(supervisor, op_data, pc);
- /* Execute any probes. */
- done_catchalls = 0;
- cur_probe = (op_catchalls != NULL) ? op_catchalls->head : NULL;
- while (cur_probe != NULL || !done_catchalls) {
+ /* Execute the probes in the list. */
+ cur_probe = list->head;
+ while (cur_probe != NULL) {
PMC *callback;
- probe_node_t *next;
+ PMC *probe;
- /* 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;
+ /* Get the probe and list object. */
+ if (VTABLE_does(supervisor, cur_probe->list_obj, CONST_STRING(supervisor, "array"))) {
+ /* Obtain the probe and callback from the RPA. */
+ probe = VTABLE_get_pmc_keyed_int(supervisor, cur_probe->list_obj, 0);
+ callback = VTABLE_get_pmc_keyed_int(supervisor, cur_probe->list_obj, 1);
+ }
+ else {
+ /* Node contains the probe object. Obtain the callback from its attributes. */
+ probe = cur_probe->list_obj;
+ callback = VTABLE_get_attr_str(supervisor, probe,
+ CONST_STRING(supervisor, "$!callback"));
}
- /* Fire the probe. */
- callback = VTABLE_get_attr_str(supervisor, cur_probe->list_obj,
- CONST_STRING(supervisor, "$!callback"));
- next = cur_probe->next;
if (!PMC_IS_NULL(callback)) {
- /* Pass params: InstrumentOp, Instrument, Instrument::Probe */
+ /* Pass params: InstrumentOp, Instrument, Instrument::Probe.
+ If a PMC is returned, only push it into the recall list if
+ it is invokable. */
+ PMC *recall = PMCNULL;
Parrot_ext_call(supervisor, callback,
- "PPP->",
- op_data, instrument, cur_probe->list_obj);
+ "PPP->P",
+ op_data, instrument, probe,
+ &recall);
+ if (!PMC_IS_NULL(recall) && VTABLE_does(supervisor, recall,
+ CONST_STRING(supervisor, "invokable"))) {
+ PMC *list_entry;
+
+ list_entry = Parrot_pmc_new(supervisor, enum_class_ResizablePMCArray);
+ VTABLE_push_pmc(supervisor, list_entry, cur_probe->list_obj);
+ VTABLE_push_pmc(supervisor, list_entry, recall);
+
+ probe_list_push(supervisor, recall_list, list_entry);
+ }
}
- cur_probe = next;
+
+ /* Go on to next entry. */
+ cur_probe = cur_probe->next;
}
- /* Done */
- return pc;
+ /* Cleanup list and return. */
+ probe_list_delete_list(supervisor, list);
+ return recall_list;
}
/*
@@ -786,7 +865,7 @@
PMC *iter;
/* Normalise the vtables of both interps due to singletons. */
- normalise_vtables(interp, supervisor);
+ fixup_vtables(interp, supervisor);
/* Before we normalise the op tables, we need to update the hooks table. */
Instrument_init_probes(supervisor, interp);
@@ -820,7 +899,7 @@
/*
* Normalise the vtables between the source and dest interpreters.
*/
-static void normalise_vtables(Parrot_Interp src, Parrot_Interp dest) {
+static void fixup_vtables(Parrot_Interp src, Parrot_Interp dest) {
INTVAL i;
/* Extend dest's vtable. */
Modified: branches/gsoc_instrument/src/dynpmc/instrumentgc.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrumentgc.pmc Mon Jul 19 09:38:32 2010 (r48110)
+++ branches/gsoc_instrument/src/dynpmc/instrumentgc.pmc Mon Jul 19 16:38:22 2010 (r48111)
@@ -665,6 +665,8 @@
}
void destroy_gc_common_hashes(PARROT_INTERP) {
+ if (gc_registry == NULL) { return; }
+
if (parrot_hash_size(interp, gc_registry) == 0) {
parrot_hash_destroy(interp, gc_registry);
parrot_hash_destroy(interp, gc_name_stubs);
@@ -672,6 +674,10 @@
parrot_hash_destroy(interp, gc_item_groups);
gc_first_run = 1;
+ gc_registry = NULL;
+ gc_name_stubs = NULL;
+ gc_group_items = NULL;
+ gc_item_groups = NULL;
}
}
Modified: branches/gsoc_instrument/src/dynpmc/instrumentvtable.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrumentvtable.pmc Mon Jul 19 09:38:32 2010 (r48110)
+++ branches/gsoc_instrument/src/dynpmc/instrumentvtable.pmc Mon Jul 19 16:38:22 2010 (r48111)
@@ -3209,6 +3209,8 @@
}
void destroy_vtable_common_hashes(PARROT_INTERP) {
+ if (vtable_registry == NULL) { return; }
+
if (parrot_hash_size(interp, vtable_registry) == 0) {
parrot_hash_destroy(interp, vtable_registry);
parrot_hash_destroy(interp, vtable_name_stubs);
@@ -3216,6 +3218,10 @@
parrot_hash_destroy(interp, vtable_item_groups);
vtable_first_run = 1;
+ vtable_registry = NULL;
+ vtable_name_stubs = NULL;
+ vtable_group_items = NULL;
+ vtable_item_groups = NULL;
}
}
More information about the parrot-commits
mailing list