[svn:parrot] r48264 - branches/gsoc_instrument/src/dynpmc

khairul at svn.parrot.org khairul at svn.parrot.org
Tue Aug 3 03:16:38 UTC 2010


Author: khairul
Date: Tue Aug  3 03:16:38 2010
New Revision: 48264
URL: https://trac.parrot.org/parrot/changeset/48264

Log:
Updated method instrumentation.

Added:
   branches/gsoc_instrument/src/dynpmc/instrumentinvokable.pmc
Modified:
   branches/gsoc_instrument/src/dynpmc/instrumentclass.pmc
   branches/gsoc_instrument/src/dynpmc/instrumentobject.pmc

Modified: branches/gsoc_instrument/src/dynpmc/instrumentclass.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrumentclass.pmc	Tue Aug  3 03:13:36 2010	(r48263)
+++ branches/gsoc_instrument/src/dynpmc/instrumentclass.pmc	Tue Aug  3 03:16:38 2010	(r48264)
@@ -13,11 +13,6 @@
 to know when a method is called, simply instrumenting the invoke vtable
 entry of the method is enough.
 
-=head2 TODO
-
-1. Documentation.
-2. Figure out how to access the params.
-
 =head2 Methods
 
 =over 4
@@ -27,6 +22,7 @@
 */
 
 #include "pmc_instrument.h"
+#include "pmc/pmc_class.h"
 
 pmclass InstrumentClass auto_attrs dynpmc group instrument_group extends InstrumentVtable {
     ATTR PMC *instrumented_methods;
@@ -108,8 +104,8 @@
         GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
 
         _class  = Parrot_oo_get_class_str(supervised, attr->class_name);
-        (PMC *methods) = PCCINVOKE(INTERP, _class, "methods");
-        method_sub     = VTABLE_get_pmc_keyed_str(INTERP, methods, method);
+        GETATTR_Class_methods(supervised, _class, methods);
+        method_sub     = VTABLE_get_pmc_keyed_str(supervised, methods, method);
 
         /* Ensure that method exists. */
         if (PMC_IS_NULL(method_sub)) {
@@ -122,20 +118,21 @@
         count = VTABLE_get_integer_keyed_str(INTERP, attr->instrumented_methods, method);
         if (count == 0) {
             /* Method was not instrumented before. */
-            (PMC *instr_obj) =
-                PCCINVOKE(INTERP, attr->instrument, "instrument_object", PMC *method_sub);
+            PMC *invokable, *event;
+            INTVAL type;
+
+            type     = Parrot_pmc_get_type_str(INTERP, CONST_STRING(INTERP, "InstrumentInvokable"));
+            invokable= Parrot_pmc_new_init(INTERP, type, attr->instrument);
 
-            /* Instrument its invoke vtable entry. */
-            () = PCCINVOKE(INTERP, instr_obj, "insert_hook", STRING *invoke);
+            event    = VTABLE_clone(INTERP, attr->event_prefix);
+            VTABLE_push_string(INTERP, event, CONST_STRING(INTERP, "method"));
+            VTABLE_push_string(INTERP, event, method);
 
-            /* Add an entry into the rename_hash attribute so that when an event
-               is raised, the event properly named. */
-            rename = VTABLE_clone(INTERP, attr->event_prefix);
-            VTABLE_push_string(INTERP, rename , CONST_STRING(INTERP, "method"));
-            VTABLE_push_string(INTERP, rename , method);
+            () = PCCINVOKE(INTERP, invokable, "set_event", PMC *event);
 
-            GETATTR_InstrumentVtable_rename_hash(INTERP, instr_obj, rename_hash);
-            VTABLE_set_pmc_keyed_str(INTERP, rename_hash, invoke, rename);
+            VTABLE_set_pointer(INTERP, invokable, method_sub);
+
+            VTABLE_set_pmc_keyed_str(supervised, methods, method, invokable);
         }
 
         /* Update count. */
@@ -164,8 +161,8 @@
         GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
 
         _class  = Parrot_oo_get_class_str(supervised, attr->class_name);
-        (PMC *methods) = PCCINVOKE(INTERP, _class, "methods");
-        method_sub     = VTABLE_get_pmc_keyed_str(INTERP, methods, method);
+        GETATTR_Class_methods(supervised, _class, methods);
+        method_sub     = VTABLE_get_pmc_keyed_str(supervised, methods, method);
 
         /* Ensure that method exists. */
         if (PMC_IS_NULL(method_sub)) {
@@ -184,17 +181,10 @@
         }
         else if (count == 1) {
             /* Remove the instrumentation. */
-            invoke = CONST_STRING(INTERP, "invoke");
-
-            /* The InstrumentObject instance for the override can
-               be obtained from the registry using the vtable pointer. */
-            instr_obj = (PMC *) parrot_hash_get(INTERP, attr->registry, method_sub->vtable);
-
-            /* Instrument its invoke vtable entry. */
-            () = PCCINVOKE(INTERP, instr_obj, "remove_hook", STRING *invoke);
+            PMC *orig_method_sub;
 
-            GETATTR_InstrumentVtable_rename_hash(INTERP, instr_obj, rename_hash);
-            VTABLE_delete_keyed_str(INTERP, rename_hash, invoke);
+            orig_method_sub = (PMC *) VTABLE_get_pointer(INTERP, method_sub);
+            VTABLE_set_pmc_keyed_str(supervised, methods, method, orig_method_sub);
         }
 
         /* Update count. */

Added: branches/gsoc_instrument/src/dynpmc/instrumentinvokable.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_instrument/src/dynpmc/instrumentinvokable.pmc	Tue Aug  3 03:16:38 2010	(r48264)
@@ -0,0 +1,260 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id: instrumentobject.pmc 48183 2010-07-27 06:49:44Z khairul $
+
+=head1 NAME
+
+src/dynpmc/instrumentinvokable.pmc - InstrumentInvokable
+
+=head1 DESCRIPTION
+
+InstrumentInvokable is used internally to serve as an
+intermediary for invokables. This is used in InstrumentClass
+and InstrumentObject to intercept the method and vtable override
+calls.
+
+=head2 Methods
+
+=over 4
+
+=cut
+
+*/
+
+#include "pmc_instrument.h"
+
+#include "instrument_private.h"
+#include "instrument_extern.h"
+
+pmclass InstrumentInvokable auto_attrs dynpmc group instrument_group {
+    ATTR PMC    *invokable;
+    ATTR PMC    *instrument;
+    ATTR STRING *event;
+    ATTR Parrot_Interp interp;
+
+/*
+
+=item C<void init_pmc(PMC *instrument)>
+
+Initialises the attributes.
+
+=cut
+
+*/
+
+    VTABLE void init_pmc(PMC *instrument) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+
+        attr->invokable  = PMCNULL;
+        attr->event      = CONST_STRING(INTERP, "");
+        attr->instrument = instrument;
+        attr->interp     = INTERP;
+    }
+
+/*
+
+=item C<opcode_t* invoke (void *next)>
+
+When invoked, raises an event with the data holding the call context
+instance. To get another event when the invokable has done executing,
+return an invokable when the first event is raised.
+
+=cut
+
+*/
+
+    VTABLE opcode_t* invoke (void *next) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        Parrot_Interp supervised;
+        Parrot_Context_info info;
+        PMC *task_hash, *task, *data, *recall;
+        PMC *instrument;
+        STRING *event;
+        opcode_t *ret;
+
+        GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
+        INTERP     = attr->interp;
+        instrument = attr->instrument;
+        event      = attr->event;
+
+        data = Parrot_pmc_new(INTERP, enum_class_Hash);
+        VTABLE_set_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "call_sig"),
+                                 CURRENT_CONTEXT(supervised));
+
+        (PMC *recall) = PCCINVOKE(INTERP, instrument, "raise_event", STRING *event, PMC *data);
+        ret = VTABLE_invoke(supervised, attr->invokable, next);
+        (PMC *recall) = PCCINVOKE(INTERP, instrument, "raise_event",
+                                  STRING *event, PMC *data, PMC *recall);
+        probe_list_delete_list(INTERP, (probe_list_t *)VTABLE_get_pointer(INTERP, recall));
+
+        return ret;
+    }
+
+/*
+
+=item C<void set_pointer(void *invokable)>
+
+Sets the invokable to invoke when the vtable invoke is called.
+
+=cut
+
+*/
+
+    VTABLE void set_pointer(void *invokable) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        attr->invokable = (PMC *) invokable;
+    }
+
+/*
+
+=item C<void* get_pointer()>
+
+Returns the invokable PMC that was attached to this instance.
+
+=cut
+
+*/
+
+    VTABLE void* get_pointer() {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        return attr->invokable;
+    }
+
+/*
+
+=item C<STRING* name()>
+
+Returns the name of the invokable PMC that was attached to this instance.
+
+=cut
+
+*/
+
+    VTABLE STRING* name() {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        Parrot_Interp supervised;
+        GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
+        return VTABLE_name(supervised, attr->invokable);
+    }
+
+/*
+
+=item C<STRING* get_string()>
+
+Returns the string representation of the
+invokable PMC that was attached to this instance.
+
+=cut
+
+*/
+
+    VTABLE STRING* get_string() {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        return VTABLE_get_string(INTERP, attr->invokable);
+    }
+
+/*
+
+=item C<INTVAL isa(STRING *isa)>
+=item C<INTVAL isa_pmc(PMC *isa)>
+
+Pass through the isa call to the invokable.
+
+=cut
+
+*/
+
+    VTABLE INTVAL isa(STRING *isa) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        return VTABLE_isa(INTERP, attr->invokable, isa);
+    }
+
+    VTABLE INTVAL isa_pmc(PMC *isa) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        return VTABLE_isa_pmc(INTERP, attr->invokable, isa);
+    }
+
+/*
+
+=item C<PMC* clone()>
+
+Pass through the clone call to the invokable.
+
+=cut
+
+*/
+
+    VTABLE PMC* clone() {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        return VTABLE_clone(INTERP, attr->invokable);
+    }
+
+/*
+
+=item C<void thaw(PMC *info)>
+
+Thaws the InstrumentInvokable instance and the invokable
+out of the given ImageIO instance.
+
+=cut
+
+*/
+
+    VTABLE void thaw(PMC *info) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+
+        attr->invokable  = (PMC *) VTABLE_shift_integer(INTERP, info);
+        attr->instrument = (PMC *) VTABLE_shift_integer(INTERP, info);
+        attr->interp     = (Parrot_Interp) VTABLE_shift_integer(INTERP, info);
+        attr->event      = VTABLE_shift_string(INTERP, info);
+
+        VTABLE_thaw(INTERP, attr->invokable, info);
+    }
+
+/*
+
+=item C<void thaw(PMC *info)>
+
+Freezes the InstrumentInvokable instance and the invokable
+into the given ImageIO instance.
+
+=cut
+
+*/
+
+     VTABLE void freeze(PMC *info) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+
+        VTABLE_push_integer(INTERP, info, (INTVAL) attr->invokable);
+        VTABLE_push_integer(INTERP, info, (INTVAL) attr->instrument);
+        VTABLE_push_integer(INTERP, info, (INTVAL) attr->interp);
+        VTABLE_push_string(INTERP, info, attr->event);
+
+        VTABLE_freeze(INTERP, attr->invokable, info);
+     }
+
+/*
+
+=item C<void set_event(PMC *event)>
+
+Given an array of event tokens, eq ['Class','Eg','method','foo'],
+joins the array together to form the event to be raised whenever
+this instance is invoked.
+
+=cut
+
+*/
+
+    METHOD set_event (PMC *event) {
+        Parrot_InstrumentInvokable_attributes * const attr = PARROT_INSTRUMENTINVOKABLE(SELF);
+        attr->event = Parrot_str_join(INTERP, CONST_STRING(INTERP, "::"), event);
+    }
+}
+
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: branches/gsoc_instrument/src/dynpmc/instrumentobject.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrumentobject.pmc	Tue Aug  3 03:13:36 2010	(r48263)
+++ branches/gsoc_instrument/src/dynpmc/instrumentobject.pmc	Tue Aug  3 03:16:38 2010	(r48264)
@@ -20,13 +20,15 @@
 */
 
 #include "pmc_instrument.h"
+#include "pmc/pmc_class.h"
+#include "pmc/pmc_object.h"
 
 extern
 void setup_vtable_individual_hashes(PARROT_INTERP, Hash *orig_hash, Hash *instr_hash,
                                     _vtable *vt_orig, _vtable *vt_instr);
 
 pmclass InstrumentObject auto_attrs dynpmc group instrument_group extends InstrumentClass {
-
+    ATTR PMC *object;
 /*
 
 =item C<void attach_to_class(STRING *classname)>
@@ -58,10 +60,12 @@
     METHOD attach_to_object(PMC *object) {
         Parrot_InstrumentObject_attributes * const attr = PARROT_INSTRUMENTOBJECT(SELF);
         Parrot_Interp supervised;
+        PMC *_class;
         STRING *addr;
 
         GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
 
+        attr->object              = object;
         attr->class_name          = VTABLE_name(INTERP, object);
         attr->instrumented_struct = mem_gc_allocate_zeroed_typed(supervised, _vtable);
         attr->original_struct     = object->vtable;
@@ -78,52 +82,145 @@
         (STRING *addr) = PCCINVOKE(INTERP, SELF, "get_address");
         VTABLE_push_string(INTERP, attr->event_prefix, CONST_STRING(INTERP, "Object"));
         VTABLE_push_string(INTERP, attr->event_prefix, addr);
+
+        /* Create a copy of the class. */
+        _class = VTABLE_clone(supervised, VTABLE_get_class(supervised, object));
+        {
+            Parrot_Object_attributes * const obj = PARROT_OBJECT(object);
+            obj->_class = _class;
+        }
     }
 
-    METHOD get_address() {
-        STRING *addr;
-        addr = Parrot_sprintf_c(INTERP, "%p", SELF);
-        RETURN(STRING *addr);
+/*
+
+=item C<void insert_method_hook(STRING *method)>
+
+Instruments the method by the given name to raise an event when it
+is called.
+
+=cut
+
+*/
+
+    METHOD insert_method_hook(STRING *method) {
+        Parrot_InstrumentObject_attributes * const attr = PARROT_INSTRUMENTOBJECT(SELF);
+        PMC *_class, *methods, *method_sub;
+        PMC *instr_obj, *rename, *rename_hash;
+        STRING *invoke;
+        INTVAL count;
+        Parrot_Interp supervised;
+
+        invoke = CONST_STRING(INTERP, "invoke");
+
+        GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
+
+        _class  = VTABLE_get_class(supervised, attr->object);
+        GETATTR_Class_methods(supervised, _class, methods);
+        method_sub     = VTABLE_get_pmc_keyed_str(supervised, methods, method);
+
+        /* Ensure that method exists. */
+        if (PMC_IS_NULL(method_sub)) {
+            Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
+                                        "Class %Ss does not have a method named %Ss.",
+                                        attr->class_name, method);
+        }
+
+        /* Check the count for this method. */
+        count = VTABLE_get_integer_keyed_str(INTERP, attr->instrumented_methods, method);
+        if (count == 0) {
+            /* Method was not instrumented before. */
+            PMC *invokable, *event;
+            INTVAL type;
+
+            type     = Parrot_pmc_get_type_str(INTERP, CONST_STRING(INTERP, "InstrumentInvokable"));
+            invokable= Parrot_pmc_new_init(INTERP, type, attr->instrument);
+
+            event    = VTABLE_clone(INTERP, attr->event_prefix);
+            VTABLE_push_string(INTERP, event, CONST_STRING(INTERP, "method"));
+            VTABLE_push_string(INTERP, event, method);
+
+            () = PCCINVOKE(INTERP, invokable, "set_event", PMC *event);
+
+            VTABLE_set_pointer(INTERP, invokable, method_sub);
+
+            VTABLE_set_pmc_keyed_str(supervised, methods, method, invokable);
+        }
+
+        /* Update count. */
+        count++;
+        VTABLE_set_integer_keyed_str(INTERP, attr->instrumented_methods, method, count);
+    }
+
+    /*
+
+=item C<void remove_method_hook(STRING *method)>
+
+Removes the instrumentation of the given method.
+
+=cut
+
+*/
+
+    METHOD remove_method_hook(STRING *method) {
+        Parrot_InstrumentObject_attributes * const attr = PARROT_INSTRUMENTOBJECT(SELF);
+        PMC *_class, *methods, *method_sub;
+        PMC *instr_obj, *rename_hash;
+        STRING *invoke;
+        INTVAL count;
+        Parrot_Interp supervised;
+
+        GETATTR_Instrument_supervised(INTERP, attr->instrument, supervised);
+
+        _class  = VTABLE_get_class(supervised, attr->object);
+        GETATTR_Class_methods(supervised, _class, methods);
+        method_sub     = VTABLE_get_pmc_keyed_str(supervised, methods, method);
+
+        /* Ensure that method exists. */
+        if (PMC_IS_NULL(method_sub)) {
+            Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
+                                        "Class %Ss does not have a method named %Ss.",
+                                        attr->class_name, method);
+        }
+
+        /* Check the count for this method. */
+        count = VTABLE_get_integer_keyed_str(INTERP, attr->instrumented_methods, method);
+        if (count == 0) {
+            /* Not instrumented before. */
+            Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
+                                                "%Ss : No hook for method '%Ss' to remove.",
+                                                VTABLE_name(INTERP, SELF), method);
+        }
+        else if (count == 1) {
+            /* Remove the instrumentation. */
+            PMC *orig_method_sub;
+
+            orig_method_sub = (PMC *) VTABLE_get_pointer(INTERP, method_sub);
+            VTABLE_set_pmc_keyed_str(supervised, methods, method, orig_method_sub);
+        }
+
+        /* Update count. */
+        count--;
+        VTABLE_set_integer_keyed_str(INTERP, attr->instrumented_methods, method, count);
     }
-}
 
 /*
- static
-opcode_t *
-stub_object_invoke(PARROT_INTERP, PMC *pmc, opcode_t *dest) {
-    PMC *instr_vt, *data;
-    void *orig_vtable;
-    Parrot_Interp supervisor;
-    PMC *temp;
-    PMC *params;
-    opcode_t* ret;
-
-    instr_vt = (PMC *) parrot_hash_get(interp, vtable_registry, pmc->vtable);
-
-    GETATTR_InstrumentVtable_original_struct(interp, instr_vt, orig_vtable);
-    GETATTR_InstrumentVtable_supervisor(interp, instr_vt, supervisor);
-
-    params = Parrot_pmc_new(supervisor, enum_class_ResizablePMCArray);
-    VTABLE_push_pmc(supervisor, params, pmc);
-    temp = Parrot_pmc_new(supervisor, enum_class_Pointer);
-    VTABLE_set_pointer(supervisor, temp, next);
-    VTABLE_push_pmc(supervisor, params, temp);
-
-
-    data = Parrot_pmc_new(supervisor, enum_class_Hash);
-    VTABLE_set_pmc_keyed_str(supervisor, data,
-        CONST_STRING(supervisor, "parameters"),
-        params);
-
-    raise_vtable_event(supervisor, interp, instr_vt, pmc, data,
-                   CONST_STRING(supervisor, "main"),
-                   CONST_STRING(supervisor, "invoke"));
 
+=item C<STRING* get_address()>
 
-    ret = ((_vtable *)orig_vtable)->invoke(interp, pmc, next);
-    return ret;
+Instruments the method by the given name to raise an event when it
+is called.
+
+=cut
+
+*/
+
+    METHOD get_address() {
+        Parrot_InstrumentObject_attributes * const attr = PARROT_INSTRUMENTOBJECT(SELF);
+        STRING *addr;
+        addr = Parrot_sprintf_c(INTERP, "%p", attr->object);
+        RETURN(STRING *addr);
+    }
 }
- */
 
 /*
 


More information about the parrot-commits mailing list