[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