Author: julianalbo Date: Sun Jan 25 11:20:43 2009 New Revision: 36004 Modified: trunk/include/parrot/scheduler.h trunk/src/ops/core.ops trunk/src/pmc/scheduler.pmc trunk/src/scheduler.c trunk/t/pmc/exception.t
Log: fix count_eh opcode and add test for it, TT #212 rg++ Modified: trunk/include/parrot/scheduler.h ============================================================================== --- trunk/include/parrot/scheduler.h (original) +++ trunk/include/parrot/scheduler.h Sun Jan 25 11:20:43 2009 @@ -36,6 +36,12 @@ __attribute__nonnull__(2); PARROT_EXPORT +INTVAL Parrot_cx_count_handlers_local(PARROT_INTERP, + ARGIN(STRING *handler_type)) + __attribute__nonnull__(1) + __attribute__nonnull__(2); + +PARROT_EXPORT INTVAL Parrot_cx_count_handlers_typed(PARROT_INTERP, ARGIN(STRING *handler_type)) __attribute__nonnull__(1) @@ -171,6 +177,10 @@ #define ASSERT_ARGS_Parrot_cx_broadcast_message __attribute__unused__ int _ASSERT_ARGS_CHECK = \ PARROT_ASSERT_ARG(interp) \ || PARROT_ASSERT_ARG(messagetype) +#define ASSERT_ARGS_Parrot_cx_count_handlers_local \ + __attribute__unused__ int _ASSERT_ARGS_CHECK = \ + PARROT_ASSERT_ARG(interp) \ + || PARROT_ASSERT_ARG(handler_type) #define ASSERT_ARGS_Parrot_cx_count_handlers_typed \ __attribute__unused__ int _ASSERT_ARGS_CHECK = \ PARROT_ASSERT_ARG(interp) \ Modified: trunk/src/ops/core.ops ============================================================================== --- trunk/src/ops/core.ops (original) +++ trunk/src/ops/core.ops Sun Jan 25 11:20:43 2009 @@ -866,7 +866,7 @@ } inline op count_eh(out INT) { - $1 = Parrot_cx_count_handlers_typed(interp, + $1 = Parrot_cx_count_handlers_local(interp, string_from_cstring(interp, "exception", 9)); } Modified: trunk/src/pmc/scheduler.pmc ============================================================================== --- trunk/src/pmc/scheduler.pmc (original) +++ trunk/src/pmc/scheduler.pmc Sun Jan 25 11:20:43 2009 @@ -513,11 +513,12 @@ METHOD count_handlers(STRING *type :optional, INTVAL have_type :opt_flag) { /* avoid uninitialized value warning */ PMC *handlers = NULL; - INTVAL elements = VTABLE_elements(INTERP, handlers); + INTVAL elements; INTVAL count = 0; INTVAL index; GET_ATTR_handlers(INTERP, SELF, handlers); + elements = VTABLE_elements(INTERP, handlers); if (!have_type) RETURN(INTVAL elements); Modified: trunk/src/scheduler.c ============================================================================== --- trunk/src/scheduler.c (original) +++ trunk/src/scheduler.c Sun Jan 25 11:20:43 2009 @@ -559,6 +559,73 @@ /* +=item C<INTVAL Parrot_cx_count_handlers_local> + +Count the number of active handlers of a particular type from the +context's list of handlers. + +=cut + +*/ + +PARROT_EXPORT +INTVAL +Parrot_cx_count_handlers_local(PARROT_INTERP, ARGIN(STRING *handler_type)) +{ + ASSERT_ARGS(Parrot_cx_count_handlers_local) + PMC *handlers = CONTEXT(interp)->handlers; + INTVAL elements; + + if (PMC_IS_NULL(handlers)) + return 0; + + elements = VTABLE_elements(interp, handlers); + + if (STRING_IS_NULL(handler_type) || STRING_IS_EMPTY(handler_type)) + return elements; + + /* Loop from newest handler to oldest handler. */ + { + STRING *exception_str = CONST_STRING(interp, "exception"); + STRING *event_str = CONST_STRING(interp, "event"); + STRING *handler_str = CONST_STRING(interp, "ExceptionHandler"); + INTVAL count = 0; + INTVAL index; + typedef enum { Hunknown, Hexception, Hevent } Htype; + + const Htype htype = + (string_equal(interp, handler_type, exception_str) == 0) ? + Hexception : + (string_equal(interp, handler_type, event_str) == 0) ? + Hevent : + Hunknown; + STRING * const handler_name = (htype == Hexception) ? + handler_str : (STRING *) NULL; + + for (index = 0; index < elements; ++index) { + PMC *handler = VTABLE_get_pmc_keyed_int(interp, handlers, index); + if (!PMC_IS_NULL(handler)) { + switch (htype) { + case Hexception: + if (VTABLE_isa(interp, handler, handler_name)) + count++; + break; + case Hevent: + if (handler->vtable->base_type == enum_class_EventHandler) + count++; + break; + default: + break; + } + } + } + return count; + } +} + + +/* + =item C<void Parrot_cx_add_handler> Add a task handler to scheduler's list of handlers. @@ -625,7 +692,7 @@ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Scheduler was not initialized for this interpreter.\n"); - Parrot_PCCINVOKE(interp, interp->scheduler, CONST_STRING(interp, "count_handlers"), "S->I", handler_type, count); + Parrot_PCCINVOKE(interp, interp->scheduler, CONST_STRING(interp, "count_handlers"), "S->I", handler_type, &count); return count; } Modified: trunk/t/pmc/exception.t ============================================================================== --- trunk/t/pmc/exception.t (original) +++ trunk/t/pmc/exception.t Sun Jan 25 11:20:43 2009 @@ -6,7 +6,7 @@ use warnings; use lib qw( . lib ../lib ../../lib ); use Test::More; -use Parrot::Test tests => 30; +use Parrot::Test tests => 31; =head1 NAME @@ -715,6 +715,45 @@ no segfault OUTPUT +pir_output_is( <<'CODE', <<'OUTPUT', "count_eh" ); +.sub main :main + $I0 = count_eh + if $I0 == 0 goto right_number1 + print "not " + right_number1: + print "ok 1\n" + push_eh _handler1 + push_eh _handler2 + print "ok 2\n" + $I1 = count_eh + if $I1 == 2 goto right_number2 + print "not " + right_number2: + print "ok 3\n" + pop_eh + pop_eh + print "ok 4\n" + $I2 = count_eh + if $I2 == 0 goto right_number3 + print "not " + right_number3: + print "ok 5\n" + end +_handler1: + print "first handler\n" + end +_handler2: + print "second handler\n" + end +.end +CODE +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +OUTPUT + # Local Variables: # mode: cperl # cperl-indent-level: 4