[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