[svn:parrot] r47625 - in branches/gsoc_instrument: runtime/parrot/library/Instrument src/dynpmc src/runcore
khairul at svn.parrot.org
khairul at svn.parrot.org
Mon Jun 14 17:55:01 UTC 2010
Author: khairul
Date: Mon Jun 14 17:55:01 2010
New Revision: 47625
URL: https://trac.parrot.org/parrot/changeset/47625
Log:
Added detecting dynlib loading
Modified:
branches/gsoc_instrument/runtime/parrot/library/Instrument/Base.nqp
branches/gsoc_instrument/runtime/parrot/library/Instrument/Event.nqp
branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp
branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp
branches/gsoc_instrument/src/dynpmc/instrument.pmc
branches/gsoc_instrument/src/runcore/main.c
Modified: branches/gsoc_instrument/runtime/parrot/library/Instrument/Base.nqp
==============================================================================
--- branches/gsoc_instrument/runtime/parrot/library/Instrument/Base.nqp Mon Jun 14 16:57:14 2010 (r47624)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/Base.nqp Mon Jun 14 17:55:01 2010 (r47625)
@@ -191,4 +191,4 @@
};
};
-# vim: ft=perl6 expandtab shiftwidth=4:
\ No newline at end of file
+# vim: ft=perl6 expandtab shiftwidth=4:
Modified: branches/gsoc_instrument/runtime/parrot/library/Instrument/Event.nqp
==============================================================================
--- branches/gsoc_instrument/runtime/parrot/library/Instrument/Event.nqp Mon Jun 14 16:57:14 2010 (r47624)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/Event.nqp Mon Jun 14 17:55:01 2010 (r47625)
@@ -61,7 +61,9 @@
=end
method _on_attach () {
- $!instr_obj.attach($!probe_obj);
+ if pir::defined__IP($!probe_obj) {
+ $!instr_obj.attach($!probe_obj);
+ }
my $dispatcher := Q:PIR {
$P0 = getattribute self, '$!instr_obj'
@@ -117,4 +119,4 @@
}
};
-# vim: ft=perl6 expandtab shiftwidth=4:
\ No newline at end of file
+# vim: ft=perl6 expandtab shiftwidth=4:
Modified: branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp
==============================================================================
--- branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp Mon Jun 14 16:57:14 2010 (r47624)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/EventLibrary.nqp Mon Jun 14 17:55:01 2010 (r47625)
@@ -34,8 +34,7 @@
=item Instrument::Event::Internal::loadlib
Raises an event whenever a dynlib is loaded.
-
-TODO: Need some C code for .loadlib directives. Not sure how to yet.
+Events are raised in the C code.
=cut
=end
@@ -44,27 +43,7 @@
method _self_init() {
$!event_type := 'Instrument::Event::Internal::loadlib';
-
- $!probe_obj := Instrument::Probe.new();
-
- $!probe_obj.inspect('loadlib');
- $!probe_obj.set_callback(pir::get_global__PS('callback'));
- };
-
- sub callback ($pc, $op, $instr_obj) {
- my $op_lib := Q:PIR { %r = new ['OpLib'] };
- my $op_code := pir::set_p_p_ki__PPI($op_lib, $op[0]);
- my $arg_type := pir::set_i_p_ki__IPI($op_code, 1);
- my $lib := $instr_obj.get_op_arg($op[2], $arg_type);
-
- my $data := Q:PIR { %r = new ['ResizablePMCArray'] };
- $data.push($lib);
- $data.push($pc);
- $data.push($op);
- $data.push($instr_obj);
-
- Instrument::Event::_raise_event('Instrument::Event::Internal::loadlib', $data);
- };
+ };
};
=begin
@@ -142,4 +121,4 @@
};
};
-# vim: ft=perl6 expandtab shiftwidth=4:
\ No newline at end of file
+# vim: ft=perl6 expandtab shiftwidth=4:
Modified: branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp
==============================================================================
--- branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp Mon Jun 14 16:57:14 2010 (r47624)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp Mon Jun 14 17:55:01 2010 (r47625)
@@ -11,10 +11,12 @@
=head1 SYNOPSIS
## In PIR.
-
+ .local pmc probe_class
+ probe_class = get_hll_global ['Instrument'], 'Probe'
+
# Create a probe that will be called whenever the
# specified ops are encountered.
- probe = new ['Instrument';'Probe']
+ probe = probe_class.'new'()
probe.'inspect'('lt')
probe.'inspect'('gt')
probe.'set_callback'('specific_callback')
@@ -22,7 +24,7 @@
# Create a catchall probe which will be called for
# each op.
- probe = new ['Instrument';'Probe']
+ probe = probe_class.'new'()
probe.'make_catchall'()
probe.'set_callback'('catchall_callback')
probe.'set_finalize'('catchall_finalize')
Modified: branches/gsoc_instrument/src/dynpmc/instrument.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrument.pmc Mon Jun 14 16:57:14 2010 (r47624)
+++ branches/gsoc_instrument/src/dynpmc/instrument.pmc Mon Jun 14 17:55:01 2010 (r47625)
@@ -26,6 +26,7 @@
/*
* Structures for the linked list data type.
+ * TODO: Await merge to trunk of bacek's list. Then we use that instead.
*/
typedef struct probe_node_t {
@@ -56,6 +57,7 @@
PMC *supervisor_pmc;
probe_list_t **op_hooks;
probe_list_t *op_catchall;
+ PMC *old_dynlibs;
} Instrument_runcore_t;
/* Runcore Function Prototypes */
@@ -66,6 +68,11 @@
/* Helper prototype */
static opcode_t *Instrument_fire_hooks(opcode_t *pc, PARROT_INTERP);
+/* dynlib detection */
+static void normalise_vtables(Parrot_Interp src, Parrot_Interp dest);
+static void normalise_op_tables(Parrot_Interp src, Parrot_Interp dest);
+static void detect_loadlib(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);
@@ -155,10 +162,12 @@
VTABLE void mark() {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
/* Mark attributes as alive */
Parrot_gc_mark_PMC_alive_fun(INTERP, attr->probes);
Parrot_gc_mark_PMC_alive_fun(INTERP, attr->evt_dispatcher);
+ Parrot_gc_mark_PMC_alive_fun(INTERP, core->old_dynlibs);
}
/*
@@ -243,14 +252,8 @@
}
}
- /* TODO: Apparently, dynpmcs also have the same problem as dynops.
- I'm not sure why, but it seems that whenever 2 interps try
- to load the same dynpmc (at different times), something bad happens.
- Below is a hack as a temporary work around for that.
- */
- attr->supervised->vtables = INTERP->vtables;
- attr->supervised->n_vtable_max = INTERP->n_vtable_max;
- attr->supervised->n_vtable_alloced = INTERP->n_vtable_alloced;
+ /* Normalise the vtables */
+ normalise_vtables(INTERP, attr->supervised);
/* Begin Execution */
status = imcc_run(attr->supervised,
@@ -566,7 +569,13 @@
break;
case PARROT_ARG_KC:
/* Key is String reg or String const */
- ret = (Parrot_pcc_get_constants(attr->supervised, cc)[arg])->u.key;
+ ret = Parrot_pmc_new(INTERP, enum_class_String);
+ {
+ PMC *key;
+ key = (Parrot_pcc_get_constants(attr->supervised, cc)[arg])->u.key;
+
+ VTABLE_set_string_native(INTERP, ret, VTABLE_get_string(attr->supervised, key));
+ }
break;
case PARROT_ARG_KI:
@@ -607,32 +616,20 @@
Instrument_runcore_t *core = (Instrument_runcore_t *) runcore;
Parrot_Interp supervisor = core->supervisor_interp;
+ /* Detect any dynlib loading, for example during load_bytecode. */
+ detect_loadlib(interp);
+
while (pc) {
+ opcode_t *pc_copy = 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;
-
- if(supervisor->evc_func_table != NULL) {
- mem_gc_free(supervisor, supervisor->evc_func_table);
-
- supervisor->evc_func_table = NULL;
- supervisor->save_func_table = NULL;
- }
- }
-
Instrument_fire_hooks(pc, interp);
DO_OP(pc, interp);
+
+ /* Todo: Move this to a probe. This detects loadlib opcodes. */
+ if(*pc_copy >= 96 && *pc_copy <= 101) {
+ detect_loadlib(interp);
+ }
/* Force events */
Parrot_cx_handle_tasks(interp, interp->scheduler);
@@ -651,6 +648,7 @@
Instrument_runcore_init(PARROT_INTERP, Parrot_Interp supervisor, PMC *instrument) {
Instrument_runcore_t * const coredata =
mem_gc_allocate_zeroed_typed(interp, Instrument_runcore_t);
+ PMC *dynlibs = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_DYN_LIBS);
/* Ensure the current loaded runcore is the slow core */
Parrot_set_run_core(interp, PARROT_SLOW_CORE);
@@ -670,6 +668,7 @@
coredata->supervisor_pmc = instrument;
coredata->op_hooks = NULL;
coredata->op_catchall = NULL;
+ coredata->old_dynlibs = VTABLE_clone(supervisor, dynlibs);
PARROT_RUNCORE_FUNC_TABLE_SET((Parrot_runcore_t *)coredata);
@@ -757,7 +756,6 @@
/* Fire the probe. */
callback = cur_probe->list_obj;
next = cur_probe->next;
-
if (!PMC_IS_NULL(callback)) {
Parrot_ext_call(supervisor, callback, "IPP->", pc_relative, op_data, instrument);
}
@@ -769,6 +767,130 @@
}
/*
+ * Functions implementing internal detection of newly loaded dynlibs.
+ */
+
+/*
+ * Detect newly loaded dynlibs in the passed interp by comparing it
+ * with a hash of previously known loaded dynlibs.
+ */
+static void detect_loadlib(PARROT_INTERP) {
+ PMC *dynlibs, *old_dynlibs, *super_dynlibs;
+ Instrument_runcore_t *core;
+ Parrot_Interp supervisor;
+ INTVAL old_count, new_count;
+
+ core = (Instrument_runcore_t *) interp->run_core;
+ supervisor = core->supervisor_interp;
+ super_dynlibs = supervisor->iglobals;
+ old_dynlibs = core->old_dynlibs;
+ dynlibs = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_DYN_LIBS);
+
+ /* Check if any libraries were loaded. */
+ old_count = VTABLE_get_integer(supervisor, old_dynlibs);
+ new_count = VTABLE_get_integer(interp, dynlibs);
+
+ if (old_count != new_count) {
+ PMC *iter;
+
+ /* Normalise the vtables of both interps due to singletons. */
+ normalise_vtables(interp, supervisor);
+
+ /* Before we normalise the op tables, we need to update the hooks table. */
+ Instrument_init_probes(supervisor, interp);
+ normalise_op_tables(interp, supervisor);
+
+ /* Look for the new dynlibs and raise an event about them. */
+ iter = VTABLE_get_iter(interp, dynlibs);
+ while (VTABLE_get_bool(interp, iter)) {
+ PMC *key;
+
+ key = VTABLE_shift_pmc(interp, iter);
+
+ if (!VTABLE_exists_keyed(supervisor, old_dynlibs, key)) {
+ /* New lib detected. */
+ PMC *lib, *task, *task_hash, *task_data;
+
+ lib = VTABLE_get_pmc_keyed(interp, dynlibs, key);
+
+ task_data = Parrot_pmc_new(supervisor, enum_class_ResizablePMCArray);
+ VTABLE_push_string(supervisor, task_data, VTABLE_get_string(interp, lib));
+
+ task_hash = Parrot_pmc_new(supervisor, enum_class_Hash);
+ VTABLE_set_string_keyed_str(supervisor, task_hash,
+ CONST_STRING(supervisor, "type"),
+ CONST_STRING(supervisor, "event"));
+ VTABLE_set_string_keyed_str(supervisor, task_hash,
+ CONST_STRING(supervisor, "subtype"),
+ CONST_STRING(supervisor,
+ "Instrument::Event::Internal::loadlib"));
+ VTABLE_set_pmc_keyed_str(supervisor, task_hash,
+ CONST_STRING(supervisor, "data"),
+ task_data);
+
+ task = Parrot_pmc_new_init(supervisor, enum_class_Task, task_hash);
+ Parrot_cx_schedule_task(supervisor, task);
+
+ /* Add lib to the old dynlib hash */
+ VTABLE_set_pmc_keyed(supervisor, old_dynlibs, key, lib);
+ }
+ }
+ }
+
+ /* Force handling of any pending tasks in super. */
+ Parrot_cx_handle_tasks(supervisor, supervisor->scheduler);
+}
+
+/*
+ * Normalise the vtables between the source and dest interpreters.
+ */
+static void normalise_vtables(Parrot_Interp src, Parrot_Interp dest) {
+ INTVAL i;
+
+ /* Extend dest's vtable. */
+ if (dest->n_vtable_alloced < src->n_vtable_max) {
+ INTVAL new_size;
+
+ new_size = src->n_vtable_max + 16;
+
+ dest->vtables = mem_gc_realloc_n_typed_zeroed(dest, dest->vtables,
+ new_size, dest->n_vtable_alloced,
+ VTABLE *);
+ dest->n_vtable_alloced = new_size;
+ }
+
+ /* Copy over the new vtable entries. */
+ for (i = dest->n_vtable_max; i < src->n_vtable_max; i++) {
+ dest->vtables[i] = src->vtables[i];
+ }
+}
+
+/*
+ * Normalise the op tables of the dest interpreter.
+ */
+static void normalise_op_tables(Parrot_Interp src, Parrot_Interp dest) {
+ op_lib_t *core_lib;
+
+ /* Reset dest's optables if needed. */
+ core_lib = dest->run_core->opinit(dest, 1);
+ if (dest->op_count != core_lib->op_count) {
+ dest->op_count = core_lib->op_count;
+ dest->op_info_table = core_lib->op_info_table;
+ dest->op_func_table = core_lib->op_func_table;
+
+ /* Remove dest's evc_func_table */
+ if (dest->evc_func_table != NULL) {
+ mem_gc_free(dest, dest->evc_func_table);
+
+ dest->evc_func_table = NULL;
+ dest->save_func_table = NULL;
+
+ Parrot_setup_event_func_ptrs(dest);
+ }
+ }
+}
+
+/*
* Functions implementing the linked list for the probes.
*/
Modified: branches/gsoc_instrument/src/runcore/main.c
==============================================================================
--- branches/gsoc_instrument/src/runcore/main.c Mon Jun 14 16:57:14 2010 (r47624)
+++ branches/gsoc_instrument/src/runcore/main.c Mon Jun 14 17:55:01 2010 (r47625)
@@ -261,6 +261,7 @@
*/
+PARROT_EXPORT
void
Parrot_setup_event_func_ptrs(PARROT_INTERP)
{
More information about the parrot-commits
mailing list