[svn:parrot] r47381 - in branches/gsoc_instrument: src/dynpmc t/dynpmc
khairul at svn.parrot.org
khairul at svn.parrot.org
Sat Jun 5 12:10:04 UTC 2010
Author: khairul
Date: Sat Jun 5 12:10:02 2010
New Revision: 47381
URL: https://trac.parrot.org/parrot/changeset/47381
Log:
Added tests for hook insertion and removal.
Modified:
branches/gsoc_instrument/src/dynpmc/instrument.pmc
branches/gsoc_instrument/t/dynpmc/instrument.t
Modified: branches/gsoc_instrument/src/dynpmc/instrument.pmc
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/instrument.pmc Sat Jun 5 11:34:24 2010 (r47380)
+++ branches/gsoc_instrument/src/dynpmc/instrument.pmc Sat Jun 5 12:10:02 2010 (r47381)
@@ -322,18 +322,28 @@
METHOD insert_op_hook (PMC *id, INTVAL op_num, PMC *hook) {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
- probe_list_t **list = core->op_hooks;
+ probe_list_t **list = core->op_hooks;
+ size_t index = op_num;
- if(list[op_num] == NULL) {
- list[op_num] = probe_list_create_list(INTERP);
+ if(index >= attr->supervised->op_count) {
+ /* Invalid op num */
+ Parrot_ex_throw_from_c_args(
+ INTERP, NULL, 1,
+ "Invalid op number %d.",
+ index
+ );
}
- probe_list_push(INTERP, list[op_num], hook);
+ if(list[index] == NULL) {
+ list[index] = probe_list_create_list(INTERP);
+ }
+
+ probe_list_push(INTERP, list[index], hook);
}
/*
-=item C<void *remove_op_hooks(PMC *id, INTVAL op_num)>
+=item C<void *remove_op_hooks(PMC *id, INTVAL op_num, PMC *callback)>
Removes a hook for the given op number.
@@ -344,16 +354,59 @@
METHOD remove_op_hook (PMC *id, INTVAL op_num, PMC *callback) {
Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
- probe_list_t **list = core->op_hooks;
- probe_node_t *node = NULL;
+ probe_list_t **list = core->op_hooks;
+ probe_node_t *node = NULL;
+ size_t index = op_num;
+
+ if(index >= attr->supervised->op_count) {
+ /* Invalid op num */
+ Parrot_ex_throw_from_c_args(
+ INTERP, NULL, 1,
+ "Invalid op number %d.",
+ index
+ );
+ }
- if(list[op_num] != NULL) {
- node = probe_list_find(INTERP, list[op_num], callback);
+ if(list[index] != NULL) {
+ node = probe_list_find(INTERP, list[index], callback);
if(node != NULL) {
- probe_list_remove(INTERP, list[op_num], node);
+ probe_list_remove(INTERP, list[index], node);
}
}
+
+ if(node == NULL) {
+ /* Callback was not found. */
+ Parrot_ex_throw_from_c_args(
+ INTERP, NULL, 1,
+ "Probe of '%S' not found in 'removal_op_hook'",
+ VTABLE_get_string(INTERP, id)
+ );
+ }
+ }
+
+/*
+=item C<INTVAL count_op_hooks(INTVAL op_num)>
+
+Returns the number of enabled op catchall probes.
+
+=cut
+*/
+
+ METHOD count_op_hooks (INTVAL op_num) {
+ Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+ probe_list_t *list = core->op_hooks[op_num];
+ probe_node_t *node = NULL;
+ INTVAL count = 0;
+
+ node = (list != NULL) ? list->head : NULL;
+ while(node != NULL) {
+ count++;
+ node = node->next;
+ }
+
+ RETURN(INTVAL count);
}
/*
@@ -373,7 +426,7 @@
}
/*
-=item C<void *remove_op_catchall(PMC *id)>
+=item C<void *remove_op_catchall(PMC *id, PMC *callback)>
Deregister a catchall op callback
@@ -388,10 +441,43 @@
node = probe_list_find(INTERP, list, callback);
+ if(node == NULL) {
+ /* Callback was not found. */
+ Parrot_ex_throw_from_c_args(
+ INTERP, NULL, 1,
+ "Probe of '%S' not found in 'removal_op_hook'",
+ VTABLE_get_string(INTERP, id)
+ );
+ }
+
probe_list_remove(INTERP, list, node);
}
/*
+=item C<INTVAL count_op_catchalls()>
+
+Returns the number of enabled op catchall probes.
+
+=cut
+*/
+
+ METHOD count_op_catchalls () {
+ Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+ Instrument_runcore_t *core = (Instrument_runcore_t *) attr->supervised->run_core;
+ probe_list_t *list = core->op_catchall;
+ probe_node_t *node = NULL;
+ INTVAL count = 0;
+
+ node = list->head;
+ while(node != NULL) {
+ count++;
+ node = node->next;
+ }
+
+ RETURN(INTVAL count);
+ }
+
+/*
=item C<PMC *get_op_arg(INTVAL arg, INTVAL arg_type)>
Interprets arg according to arg_type and returns the value as a PMC.
@@ -419,51 +505,51 @@
break;
case PARROT_ARG_I:
ret = Parrot_pmc_new(INTERP, enum_class_Integer);
- VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(INTERP, cc, arg));
+ VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(attr->supervised, cc, arg));
break;
case PARROT_ARG_NC:
ret = Parrot_pmc_new(INTERP, enum_class_Float);
- VTABLE_set_number_native(INTERP, ret, Parrot_pcc_get_num_constant_func(INTERP, cc, arg));
+ VTABLE_set_number_native(INTERP, ret, Parrot_pcc_get_num_constant_func(attr->supervised, cc, arg));
break;
case PARROT_ARG_N:
ret = Parrot_pmc_new(INTERP, enum_class_Float);
- VTABLE_set_number_native(INTERP, ret, *Parrot_pcc_get_FLOATVAL_reg(INTERP, cc, arg));
+ VTABLE_set_number_native(INTERP, ret, *Parrot_pcc_get_FLOATVAL_reg(attr->supervised, cc, arg));
break;
case PARROT_ARG_PC:
- ret = Parrot_pcc_get_pmc_constant_func(INTERP, cc, arg);
+ ret = Parrot_pcc_get_pmc_constant_func(attr->supervised, cc, arg);
break;
case PARROT_ARG_P:
- ret = *Parrot_pcc_get_PMC_reg(INTERP, cc, arg);
+ ret = *Parrot_pcc_get_PMC_reg(attr->supervised, cc, arg);
break;
case PARROT_ARG_SC:
ret = Parrot_pmc_new(INTERP, enum_class_String);
- VTABLE_set_string_native(INTERP, ret, Parrot_pcc_get_string_constant_func(INTERP, cc, arg));
+ VTABLE_set_string_native(INTERP, ret, Parrot_pcc_get_string_constant_func(attr->supervised, cc, arg));
break;
case PARROT_ARG_S:
ret = Parrot_pmc_new(INTERP, enum_class_String);
- VTABLE_set_string_native(INTERP, ret, *Parrot_pcc_get_STRING_reg(INTERP, cc, arg));
+ VTABLE_set_string_native(INTERP, ret, *Parrot_pcc_get_STRING_reg(attr->supervised, cc, arg));
break;
case PARROT_ARG_K:
/* Key is PMC */
- ret = *Parrot_pcc_get_PMC_reg(INTERP, cc, arg);
+ ret = *Parrot_pcc_get_PMC_reg(attr->supervised, cc, arg);
break;
case PARROT_ARG_KC:
/* Key is String reg or String const */
- ret = (Parrot_pcc_get_constants(INTERP, cc)[arg])->u.key;
+ ret = (Parrot_pcc_get_constants(attr->supervised, cc)[arg])->u.key;
break;
case PARROT_ARG_KI:
/* Key is integer reg */
ret = Parrot_pmc_new(INTERP, enum_class_Integer);
- VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(INTERP, cc, arg));
+ VTABLE_set_integer_native(INTERP, ret, *Parrot_pcc_get_INTVAL_reg(attr->supervised, cc, arg));
break;
case PARROT_ARG_KIC:
@@ -517,6 +603,13 @@
supervisor->op_info_table = interp->op_info_table;
}
+ if((pc - interp->code->base.data) == 45) {
+ PMC *mro, *def;
+
+ //mro =
+ //printf("%d\n");
+ }
+
Instrument_fire_hooks(pc, interp);
DO_OP(pc, interp);
@@ -632,6 +725,7 @@
cur_probe = (op_catchalls != NULL) ? op_catchalls->head : NULL;
while(cur_probe != NULL || !done_catchalls) {
PMC *callback;
+ probe_node_t *next;
/* Switch to the specific probes if we are done with catchalls. */
if(cur_probe == NULL && !done_catchalls) {
@@ -639,15 +733,15 @@
done_catchalls = 1;
continue;
}
-
+
/* 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);
}
-
- cur_probe = cur_probe->next;
+ cur_probe = next;
}
/* Done */
@@ -666,7 +760,8 @@
list = mem_gc_allocate_zeroed_typed(interp, probe_list_t);
- list->head = list->tail = NULL;
+ list->head = NULL;
+ list->tail = NULL;
return list;
}
@@ -690,10 +785,6 @@
* Deletes the node.
*/
static void probe_list_delete_node (PARROT_INTERP, probe_node_t *node) {
- node->prev->next = node->next;
- node->next->prev = node->prev;
-
- node->next = node->prev = NULL;
mem_gc_free(interp, node);
}
@@ -745,6 +836,16 @@
static PMC * probe_list_remove (PARROT_INTERP, probe_list_t *list, probe_node_t *node) {
PMC *item;
+ if(node == list->head) {
+ list->head = node->next;
+ }
+ if(node == list->tail) {
+ list->tail = node->prev;
+ }
+
+ if(node->prev != NULL) { node->prev->next = node->next; }
+ if(node->next != NULL) { node->next->prev = node->prev; }
+
item = node->list_obj;
probe_list_delete_node(interp, node);
Modified: branches/gsoc_instrument/t/dynpmc/instrument.t
==============================================================================
--- branches/gsoc_instrument/t/dynpmc/instrument.t Sat Jun 5 11:34:24 2010 (r47380)
+++ branches/gsoc_instrument/t/dynpmc/instrument.t Sat Jun 5 12:10:02 2010 (r47381)
@@ -19,10 +19,12 @@
.sub main :main
.include 'test_more.pir'
- plan(5)
+ plan(18)
test_loadlib()
test_instantiate()
test_attach()
+ test_insert_and_remove_op_hook()
+ test_insert_and_remove_op_catchall()
.return()
.end
@@ -48,18 +50,155 @@
.end
.sub 'test_attach'
- .local pmc mock_probe, mock_id, instr
- .local pmc class, enable_method, ins, it, type
+ .local pmc mock_probe, instr
- mock_id = box 'MockProbe-0'
mock_probe = new ['MockProbe']
- setattribute mock_probe, '$!identifier', mock_id
instr = new ['Instrument']
instr.'attach'(mock_probe)
.end
+.sub 'test_insert_and_remove_op_hook'
+ # Plan: Test insertion and removal of hooks.
+ .local pmc instr
+ .local pmc stub1, stub2, fake_id
+
+ fake_id = box 'FakeProbeId'
+ stub1 = get_global 'stub_1'
+ stub2 = get_global 'stub_2'
+
+ instr = new ['Instrument']
+
+ # Test insert and remove 1 hook on existing op (op 0 = noop).
+ instr.'insert_op_hook'(fake_id, 0, stub1)
+ $I0 = instr.'count_op_hooks'(0)
+ is($I0, 1, 'Insertion successful')
+
+ instr.'remove_op_hook'(fake_id, 0, stub1)
+ $I0 = instr.'count_op_hooks'(0)
+ is($I0, 0, 'Removal successful')
+
+ # Test insert and removal 2 hooks on existing op.
+ instr.'insert_op_hook'(fake_id, 0, stub1)
+ instr.'insert_op_hook'(fake_id, 0, stub2)
+ $I0 = instr.'count_op_hooks'(0)
+ is($I0, 2, 'Insertion successful')
+
+ instr.'remove_op_hook'(fake_id, 0, stub1)
+ $I0 = instr.'count_op_hooks'(0)
+ is($I0, 1, 'Removal of probe 1 successful')
+
+ instr.'remove_op_hook'(fake_id, 0, stub2)
+ $I0 = instr.'count_op_hooks'(0)
+ is($I0, 0, 'Removal of probe 2 successful')
+
+ # Test insertion on a non-existent op. (Say, op 5000)
+ .local pmc eh
+ eh = new ['ExceptionHandler']
+ set_addr eh, NON_EXIST_OP_OK
+ push_eh eh
+
+ instr.'insert_op_hook'(fake_id, 5000, stub1)
+
+ ok(0, 'Managed to insert probe for non-existent op.')
+ goto NON_EXIST_OP_END
+
+ NON_EXIST_OP_OK:
+
+ ok(1, 'Detected non-existent op')
+
+ NON_EXIST_OP_END:
+
+ pop_eh
+
+ # Test removal of non-existent hook.
+ eh = new ['ExceptionHandler']
+ set_addr eh, NON_EXIST_PROBE_OK
+ push_eh eh
+
+ instr.'remove_op_hook'(fake_id, 0, stub1)
+
+ ok(0, 'Managed to remove non-existent probe.')
+ goto NON_EXIST_PROBE_END
+
+ NON_EXIST_PROBE_OK:
+
+ ok(1, 'Detected non-existent probe')
+
+ NON_EXIST_PROBE_END:
+
+ pop_eh
+
+.end
+
+.sub 'test_insert_and_remove_op_catchall'
+ # Plan: Test insertion and removal of catchall probes.
+ .local pmc instr
+ .local pmc stub1, stub2, fake_id
+
+ fake_id = box 'FakeCatchallProbeId'
+ stub1 = get_global 'stub_1'
+ stub2 = get_global 'stub_2'
+
+ instr = new ['Instrument']
+
+ # Test insert and remove 1 catchall.
+ instr.'insert_op_catchall'(fake_id, stub1)
+ $I0 = instr.'count_op_catchalls'()
+ is($I0, 1, 'Insertion of catchall successful')
+
+ instr.'remove_op_catchall'(fake_id, stub1)
+ $I0 = instr.'count_op_catchalls'()
+ is($I0, 0, 'Removal of catchall successful')
+
+ # Test insert and removal 2 catchalls.
+ instr.'insert_op_catchall'(fake_id, stub1)
+ instr.'insert_op_catchall'(fake_id, stub2)
+ $I0 = instr.'count_op_catchalls'()
+ is($I0, 2, 'Insertion of catchalls successful')
+
+ instr.'remove_op_catchall'(fake_id, stub1)
+ $I0 = instr.'count_op_catchalls'()
+ is($I0, 1, 'Removal of catchall probe 1 successful')
+
+ instr.'remove_op_catchall'(fake_id, stub2)
+ $I0 = instr.'count_op_catchalls'()
+ is($I0, 0, 'Removal of catchall probe 2 successful')
+
+ # Test removal of non-existent catchall hook.
+ .local pmc eh
+ eh = new ['ExceptionHandler']
+ set_addr eh, NON_EXIST_CATCHALL_OK
+ push_eh eh
+
+ instr.'remove_op_catchall'(fake_id, stub1)
+
+ ok(0, 'Managed to remove non-existent probe.')
+ goto NON_EXIST_CATCHALL_END
+
+ NON_EXIST_CATCHALL_OK:
+
+ ok(1, 'Detected non-existent probe')
+
+ NON_EXIST_CATCHALL_END:
+
+ pop_eh
+
+.end
+
+
+# Stub callbacks to test insertion and removal.
+.sub 'stub_1'
+.end
+
+.sub 'stub_2'
+.end
+
+#
+# Simple Mock of Instrument::Probe to test
+# attach.
+#
.namespace ['MockProbe']
.sub '' :anon :init :load
.local pmc class
@@ -68,6 +207,12 @@
addattribute class, '$!identifier'
.end
+.sub 'init' :vtable :method
+ $P0 = new ['String']
+ $P0 = 'MockProbe-0'
+ setattribute self, '$!identifier', $P0
+.end
+
.sub 'enable' :method
ok(1, 'Enable is called')
@@ -83,6 +228,9 @@
.return()
.end
+.sub 'disable' :method
+.end
+
# Local Variables:
# mode: pir
# fill-column: 100
More information about the parrot-commits
mailing list