Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base: master
...
compare: cached_eh
Checking mergeability… Don’t worry, you can still create the pull request.
  • 19 commits
  • 12 files changed
  • 0 commit comments
  • 1 contributor
View
1  PBC_COMPAT
@@ -28,6 +28,7 @@
# please insert tab separated entries at the top of the list
+10.1 2011.01.24 bacek add push_cached_eh into experimental.ops
10.0 2011.01.18 cotto released 3.0.0
9.0 2010.10.19 gerd released 2.9.0
8.0 2010.07.20 coke released 2.6.0
View
7 compilers/pct/src/PAST/Compiler.pir
@@ -931,9 +931,10 @@ Return the POST representation of a C<PAST::Block>.
$S0 = self.'unique'('control_')
ctrllabel = $P0.'new'('result'=>$S0)
$S0 = self.'uniquereg'('P')
- bpost.'push_pirop'('new', $S0, "['ExceptionHandler']", '.CONTROL_RETURN')
- bpost.'push_pirop'('set_addr', $S0, ctrllabel)
- bpost.'push_pirop'('push_eh', $S0)
+ #bpost.'push_pirop'('new', $S0, "['ExceptionHandler']", '.CONTROL_RETURN')
+ #bpost.'push_pirop'('set_addr', $S0, ctrllabel)
+ #bpost.'push_pirop'('push_eh', $S0)
+ bpost.'push_pirop'('push_cached_eh', '.CONTROL_RETURN', ctrllabel)
bpost.'add_directive'('.include "except_types.pasm"')
children_past:
View
1  config/gen/makefiles/root.in
@@ -1871,6 +1871,7 @@ src/ops/core_ops$(O) : src/ops/core_ops.c \
include/parrot/runcore_api.h \
include/pmc/pmc_continuation.h \
include/pmc/pmc_parrotlibrary.h \
+ include/pmc/pmc_sub.h \
src/io/io_private.h
@TEMP_gc_c@
View
93 examples/benchmarks/exceptions.pir
@@ -0,0 +1,93 @@
+.include "except_types.pasm"
+
+.sub 'test_no_eh'
+ $P0 = box 1
+ .return ($P0)
+.end
+
+.sub 'test_push_eh'
+ new $P424, ['ExceptionHandler'], .CONTROL_RETURN
+ set_addr $P424, control_return
+ push_eh $P424
+
+ $P0 = box 1
+ .return ($P0)
+
+ control_return:
+ .local pmc exception
+ .get_results (exception)
+ getattribute $P0, exception, "payload"
+
+ .return ($P0)
+.end
+
+.sub 'test_push_cached_eh'
+
+ push_cached_eh .CONTROL_RETURN, control_return
+
+ $P0 = box 1
+ .return ($P0)
+
+ control_return:
+ .local pmc exception
+ .get_results (exception)
+ getattribute $P0, exception, "payload"
+
+ .return ($P0)
+.end
+
+.sub 'test_push_cached_eh_deeply'
+ .param int depth :optional
+ .param int has_depth :opt_flag
+
+ unless has_depth goto check
+ depth = 10000
+
+ check:
+ if depth !=0 goto recure
+ .tailcall "test_push_cached_eh"()
+
+ recure:
+ dec depth
+ "test_push_cached_eh_deeply"(depth)
+.end
+
+.sub 'benchmark'
+ .param pmc sub
+ .param string desc
+
+ .local num start_time
+ start_time = time
+
+ $I0 = 0
+ loop_1:
+ if $I0 > 10000000 goto loop_1_end
+ sub()
+ inc $I0
+ goto loop_1
+ loop_1_end:
+
+ $N1 = time
+ $N2 = $N1 - start_time
+ print desc
+ print " "
+ say $N2
+
+.end
+
+.sub 'test' :main
+
+ .const "Sub" test_no_eh = "test_no_eh"
+ "benchmark"(test_no_eh, "no_eh")
+
+ .const "Sub" test_push_cached_eh = "test_push_cached_eh"
+ "benchmark"(test_push_cached_eh, "push_cached_eh")
+
+ .const "Sub" test_push_cached_eh_deeply = "test_push_cached_eh_deeply"
+ "benchmark"(test_push_cached_eh_deeply, "push_cached_eh_deeply")
+
+ .const "Sub" test_push_eh = "test_push_eh"
+ "benchmark"(test_push_eh, "push_eh")
+.end
+
+
View
3  include/parrot/oplib/core_ops.h
@@ -1090,6 +1090,9 @@ op_lib_t *Parrot_DynOp_core_3_0_0(PARROT_INTERP, long init);
opcode_t * Parrot_root_new_p_pc_i(opcode_t *, PARROT_INTERP);
opcode_t * Parrot_root_new_p_p_ic(opcode_t *, PARROT_INTERP);
opcode_t * Parrot_root_new_p_pc_ic(opcode_t *, PARROT_INTERP);
+ opcode_t * Parrot_push_cached_eh_i_ic(opcode_t *, PARROT_INTERP);
+ opcode_t * Parrot_push_cached_eh_ic_ic(opcode_t *, PARROT_INTERP);
+ opcode_t * Parrot_push_cached_eh_ic(opcode_t *, PARROT_INTERP);
#endif /* PARROT_OPLIB_CORE_OPS_H_GUARD */
View
5 include/parrot/oplib/ops.h
@@ -1083,7 +1083,10 @@ typedef enum {
PARROT_OP_root_new_p_p_i, /* 1065 */
PARROT_OP_root_new_p_pc_i, /* 1066 */
PARROT_OP_root_new_p_p_ic, /* 1067 */
- PARROT_OP_root_new_p_pc_ic /* 1068 */
+ PARROT_OP_root_new_p_pc_ic, /* 1068 */
+ PARROT_OP_push_cached_eh_i_ic, /* 1069 */
+ PARROT_OP_push_cached_eh_ic_ic, /* 1070 */
+ PARROT_OP_push_cached_eh_ic /* 1071 */
} parrot_opcode_enums;
View
3  include/parrot/opsenum.h
@@ -1083,6 +1083,9 @@ enum OPS_ENUM {
enum_ops_root_new_p_pc_i = 1066,
enum_ops_root_new_p_p_ic = 1067,
enum_ops_root_new_p_pc_ic = 1068,
+ enum_ops_push_cached_eh_i_ic = 1069,
+ enum_ops_push_cached_eh_ic_ic = 1070,
+ enum_ops_push_cached_eh_ic = 1071,
};
View
181 src/ops/core_ops.c
@@ -68,13 +68,42 @@ extern op_lib_t core_op_lib;
-INTVAL core_numops = 1070;
+#include "pmc/pmc_sub.h"
+#include "parrot/sub.h"
+
+static int
+handler_is_used(PARROT_INTERP, ARGIN(PMC *handler)) {
+ PMC *ctx, *handlers;
+ ctx = CURRENT_CONTEXT(interp);
+
+ while (!PMC_IS_NULL(ctx)) {
+ handlers = Parrot_pcc_get_handlers(interp, ctx);
+
+ if (!PMC_IS_NULL(handlers)) {
+ PMC *iter = VTABLE_get_iter(interp, handlers);
+ while (!PMC_IS_NULL(iter) && VTABLE_get_bool(interp, iter)) {
+ PMC * const test = VTABLE_shift_pmc(interp, iter);
+ if (test == handler)
+ return 1;
+ }
+ }
+
+ /* Continue the search in the next context up the chain. */
+ ctx = Parrot_pcc_get_caller_ctx(interp, ctx);
+ }
+
+ return 0;
+}
+
+
+
+INTVAL core_numops = 1073;
/*
** Op Function Table:
*/
-static op_func_t core_op_func_table[1070] = {
+static op_func_t core_op_func_table[1073] = {
Parrot_end, /* 0 */
Parrot_noop, /* 1 */
Parrot_check_events, /* 2 */
@@ -1144,6 +1173,9 @@ static op_func_t core_op_func_table[1070] = {
Parrot_root_new_p_pc_i, /* 1066 */
Parrot_root_new_p_p_ic, /* 1067 */
Parrot_root_new_p_pc_ic, /* 1068 */
+ Parrot_push_cached_eh_i_ic, /* 1069 */
+ Parrot_push_cached_eh_ic_ic, /* 1070 */
+ Parrot_push_cached_eh_ic, /* 1071 */
NULL /* NULL function pointer */
};
@@ -1154,7 +1186,7 @@ static op_func_t core_op_func_table[1070] = {
** Op Info Table:
*/
-static op_info_t core_op_info_table[1070] = {
+static op_info_t core_op_info_table[1073] = {
{ /* 0 */
/* type PARROT_INLINE_OP, */
"end",
@@ -15052,6 +15084,45 @@ static op_info_t core_op_info_table[1070] = {
{ 0, 0, 0 },
&core_op_lib
},
+ { /* 1069 */
+ /* type PARROT_FUNCTION_OP, */
+ "push_cached_eh",
+ "push_cached_eh_i_ic",
+ "Parrot_push_cached_eh_i_ic",
+ /* "", body */
+ 0,
+ 3,
+ { PARROT_ARG_I, PARROT_ARG_IC },
+ { PARROT_ARGDIR_IN, PARROT_ARGDIR_IN },
+ { 0, 1 },
+ &core_op_lib
+ },
+ { /* 1070 */
+ /* type PARROT_FUNCTION_OP, */
+ "push_cached_eh",
+ "push_cached_eh_ic_ic",
+ "Parrot_push_cached_eh_ic_ic",
+ /* "", body */
+ 0,
+ 3,
+ { PARROT_ARG_IC, PARROT_ARG_IC },
+ { PARROT_ARGDIR_IN, PARROT_ARGDIR_IN },
+ { 0, 1 },
+ &core_op_lib
+ },
+ { /* 1071 */
+ /* type PARROT_FUNCTION_OP, */
+ "push_cached_eh",
+ "push_cached_eh_ic",
+ "Parrot_push_cached_eh_ic",
+ /* "", body */
+ 0,
+ 2,
+ { PARROT_ARG_IC },
+ { PARROT_ARGDIR_IN },
+ { 1 },
+ &core_op_lib
+ },
};
@@ -25779,6 +25850,108 @@ Parrot_root_new_p_pc_ic(opcode_t *cur_opcode, PARROT_INTERP) {
return (opcode_t *)cur_opcode + 4;}
+opcode_t *
+Parrot_push_cached_eh_i_ic(opcode_t *cur_opcode, PARROT_INTERP) {
+ const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
+ PMC *current_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
+ Parrot_Sub_attributes *sub;
+ PMC *eh;
+
+ PMC_get_sub(interp, current_sub, sub);
+
+ /* Vivify eh_cache to Hash. Keys will be C<op> */
+ if (PMC_IS_NULL(sub->eh_cache)) {
+ sub->eh_cache = Parrot_pmc_new(interp, enum_class_Hash);
+ VTABLE_set_integer_native(interp, sub->eh_cache, Hash_key_type_int);
+ }
+
+ eh = VTABLE_get_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE));
+
+ /* Create new ExceptionHandler if there is none */
+ if (PMC_IS_NULL(eh) || handler_is_used(interp, eh)) {
+ eh = Parrot_pmc_new_init_int(interp, enum_class_ExceptionHandler, IREG(1));
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + ICONST(2));
+ VTABLE_set_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE), eh);
+ }
+ else {
+ /* Reinit handler */
+ VTABLE_init(interp, eh);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + ICONST(2));
+ }
+
+ /* Actually push ExceptionHandler */
+ Parrot_cx_add_handler_local(interp, eh);
+
+return (opcode_t *)cur_opcode + 3;}
+
+opcode_t *
+Parrot_push_cached_eh_ic_ic(opcode_t *cur_opcode, PARROT_INTERP) {
+ const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
+ PMC *current_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
+ Parrot_Sub_attributes *sub;
+ PMC *eh;
+
+ PMC_get_sub(interp, current_sub, sub);
+
+ /* Vivify eh_cache to Hash. Keys will be C<op> */
+ if (PMC_IS_NULL(sub->eh_cache)) {
+ sub->eh_cache = Parrot_pmc_new(interp, enum_class_Hash);
+ VTABLE_set_integer_native(interp, sub->eh_cache, Hash_key_type_int);
+ }
+
+ eh = VTABLE_get_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE));
+
+ /* Create new ExceptionHandler if there is none */
+ if (PMC_IS_NULL(eh) || handler_is_used(interp, eh)) {
+ eh = Parrot_pmc_new_init_int(interp, enum_class_ExceptionHandler, ICONST(1));
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + ICONST(2));
+ VTABLE_set_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE), eh);
+ }
+ else {
+ /* Reinit handler */
+ VTABLE_init(interp, eh);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + ICONST(2));
+ }
+
+ /* Actually push ExceptionHandler */
+ Parrot_cx_add_handler_local(interp, eh);
+
+return (opcode_t *)cur_opcode + 3;}
+
+opcode_t *
+Parrot_push_cached_eh_ic(opcode_t *cur_opcode, PARROT_INTERP) {
+ const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
+ PMC *current_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
+ Parrot_Sub_attributes *sub;
+ PMC *eh;
+
+ PMC_get_sub(interp, current_sub, sub);
+
+ /* Vivify eh_cache to Hash. Keys will be C<op> */
+ if (PMC_IS_NULL(sub->eh_cache)) {
+ sub->eh_cache = Parrot_pmc_new(interp, enum_class_Hash);
+ VTABLE_set_integer_native(interp, sub->eh_cache, Hash_key_type_int);
+ }
+
+ eh = VTABLE_get_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE));
+
+ /* Create new ExceptionHandler if there is none */
+ if (PMC_IS_NULL(eh) || handler_is_used(interp, eh)) {
+ eh = Parrot_pmc_new(interp, enum_class_ExceptionHandler);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + ICONST(1));
+ VTABLE_set_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE), eh);
+ }
+ else {
+ /* Reinit handler */
+ VTABLE_init(interp, eh);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + ICONST(1));
+ }
+
+ /* Actually push ExceptionHandler */
+ Parrot_cx_add_handler_local(interp, eh);
+
+return (opcode_t *)cur_opcode + 2;}
+
/*
** op lib descriptor:
@@ -25793,7 +25966,7 @@ op_lib_t core_op_lib = {
3, /* major_version */
0, /* minor_version */
0, /* patch_version */
- 1069, /* op_count */
+ 1072, /* op_count */
core_op_info_table, /* op_info_table */
core_op_func_table, /* op_func_table */
get_op /* op_code() */
View
100 src/ops/experimental.ops
@@ -320,6 +320,106 @@ op root_new(out PMC, in PMC, in INT) {
}
}
+=item B<push_cached_eh>(in INT, inconst LABEL)
+
+Cached version of push_eh. Creates and cache ExceptionHandler inside current Sub.
+
+=cut
+
+
+BEGIN_OPS_PREAMBLE
+
+#include "pmc/pmc_sub.h"
+#include "parrot/sub.h"
+
+static int
+handler_is_used(PARROT_INTERP, ARGIN(PMC *handler)) {
+ PMC *ctx, *handlers;
+ ctx = CURRENT_CONTEXT(interp);
+
+ while (!PMC_IS_NULL(ctx)) {
+ handlers = Parrot_pcc_get_handlers(interp, ctx);
+
+ if (!PMC_IS_NULL(handlers)) {
+ PMC *iter = VTABLE_get_iter(interp, handlers);
+ while (!PMC_IS_NULL(iter) && VTABLE_get_bool(interp, iter)) {
+ PMC * const test = VTABLE_shift_pmc(interp, iter);
+ if (test == handler)
+ return 1;
+ }
+ }
+
+ /* Continue the search in the next context up the chain. */
+ ctx = Parrot_pcc_get_caller_ctx(interp, ctx);
+ }
+
+ return 0;
+}
+
+END_OPS_PREAMBLE
+
+op push_cached_eh(in INT, inconst LABEL) {
+ PMC *current_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
+ Parrot_Sub_attributes *sub;
+ PMC *eh;
+
+ PMC_get_sub(interp, current_sub, sub);
+
+ /* Vivify eh_cache to Hash. Keys will be C<op> */
+ if (PMC_IS_NULL(sub->eh_cache)) {
+ sub->eh_cache = Parrot_pmc_new(interp, enum_class_Hash);
+ VTABLE_set_integer_native(interp, sub->eh_cache, Hash_key_type_int);
+ }
+
+ eh = VTABLE_get_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE));
+
+ /* Create new ExceptionHandler if there is none */
+ if (PMC_IS_NULL(eh) || handler_is_used(interp, eh)) {
+ eh = Parrot_pmc_new_init_int(interp, enum_class_ExceptionHandler, $1);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + $2);
+ VTABLE_set_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE), eh);
+ }
+ else {
+ /* Reinit handler */
+ VTABLE_init(interp, eh);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + $2);
+ }
+
+ /* Actually push ExceptionHandler */
+ Parrot_cx_add_handler_local(interp, eh);
+}
+
+op push_cached_eh(inconst LABEL) {
+ PMC *current_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
+ Parrot_Sub_attributes *sub;
+ PMC *eh;
+
+ PMC_get_sub(interp, current_sub, sub);
+
+ /* Vivify eh_cache to Hash. Keys will be C<op> */
+ if (PMC_IS_NULL(sub->eh_cache)) {
+ sub->eh_cache = Parrot_pmc_new(interp, enum_class_Hash);
+ VTABLE_set_integer_native(interp, sub->eh_cache, Hash_key_type_int);
+ }
+
+ eh = VTABLE_get_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE));
+
+ /* Create new ExceptionHandler if there is none */
+ if (PMC_IS_NULL(eh) || handler_is_used(interp, eh)) {
+ eh = Parrot_pmc_new(interp, enum_class_ExceptionHandler);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + $1);
+ VTABLE_set_pmc_keyed_int(interp, sub->eh_cache, PTR2INTVAL(CUR_OPCODE), eh);
+ }
+ else {
+ /* Reinit handler */
+ VTABLE_init(interp, eh);
+ VTABLE_set_pointer(interp, eh, CUR_OPCODE + $1);
+ }
+
+ /* Actually push ExceptionHandler */
+ Parrot_cx_add_handler_local(interp, eh);
+}
+
=back
=head1 COPYRIGHT
View
3  src/pmc/sub.pmc
@@ -83,6 +83,7 @@ pmclass Sub auto_attrs provides invokable {
ATTR Parrot_sub_arginfo *arg_info; /* Argument counts and flags. */
ATTR PMC *outer_ctx; /* outer context, if a closure */
+ ATTR PMC *eh_cache; /* cache for ExceptionHandlers */
/*
@@ -612,6 +613,8 @@ Marks the sub as live.
Parrot_gc_mark_PMC_alive(INTERP, sub->namespace_name);
Parrot_gc_mark_PMC_alive(INTERP, sub->multi_signature);
Parrot_gc_mark_PMC_alive(INTERP, sub->namespace_stash);
+
+ Parrot_gc_mark_PMC_alive(INTERP, sub->eh_cache);
}
/*
View
11 src/scheduler.c
@@ -489,11 +489,14 @@ void
Parrot_cx_add_handler_local(PARROT_INTERP, ARGIN(PMC *handler))
{
ASSERT_ARGS(Parrot_cx_add_handler_local)
- if (PMC_IS_NULL(Parrot_pcc_get_handlers(interp, interp->ctx)))
- Parrot_pcc_set_handlers(interp, interp->ctx, Parrot_pmc_new(interp,
- enum_class_ResizablePMCArray));
+ PMC *ctx = CURRENT_CONTEXT(interp);
+ PMC *handlers = Parrot_pcc_get_handlers(interp, ctx);
+ if (PMC_IS_NULL(handlers)) {
+ handlers = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
+ Parrot_pcc_set_handlers(interp, ctx, handlers);
+ }
- VTABLE_unshift_pmc(interp, Parrot_pcc_get_handlers(interp, interp->ctx), handler);
+ VTABLE_unshift_pmc(interp, handlers, handler);
}
View
124 t/op/push_cached_eh.t
@@ -0,0 +1,124 @@
+#!./parrot
+# Copyright (C) 2009-2010, Parrot Foundation.
+
+=head1 NAME
+
+t/op/push_cached_eh.t - Test .annotate directive
+
+=head1 SYNOPSIS
+
+ % prove t/op/push_cached_eh.t
+
+=head1 DESCRIPTION
+
+Test various use cases of the push_cached_eh opcode.
+
+=cut
+
+.include "except_types.pasm"
+
+.sub main :main
+ .include 'test_more.pir'
+
+ 'test_handle'()
+ 'test_handle'() # Call second time
+ 'test_handle_twice'()
+
+ 'test_handle_typed'()
+ 'test_handle_typed'() # Call second time
+
+ 'done_testing'()
+.end
+
+.sub "test_handle"
+ push_cached_eh catch
+
+ $P0 = new ["Exception"]
+ throw $P0
+ nok(1, "Not caught")
+
+ .return()
+
+ catch:
+ pop_eh
+ ok(1, "Caught in simple case")
+ .return()
+.end
+
+.sub "test_handle_typed"
+ push_cached_eh .CONTROL_RETURN, catch
+
+ $P0 = new ["Exception"]
+ $P0["type"] = .CONTROL_RETURN
+ throw $P0
+ nok(1, "Not caught")
+
+ goto try_again
+
+ catch:
+ pop_eh
+ ok(1, "Caught typed")
+
+
+ try_again:
+ push_cached_eh .CONTROL_RETURN, catch_typed
+ push_cached_eh .CONTROL_ERROR, catch_untyped
+
+ $P0 = new ["Exception"]
+ $P0["type"] = .CONTROL_RETURN
+ throw $P0
+ nok(1, "Not caught")
+ .return()
+
+ catch_untyped:
+ pop_eh
+ nok(1, "Caught wrong exception")
+ .return()
+
+ catch_typed:
+ pop_eh
+ ok(1, "Caught correct exception")
+ .return()
+
+
+
+ .return()
+.end
+
+
+.sub "test_handle_twice"
+ diag("First")
+ "_catch_untyped"("Caught first", "first")
+ diag("Second")
+ "_catch_untyped"("Caught second", "second")
+.end
+
+.sub '_throw'
+ .param pmc payload
+ $P0 = new ['Exception']
+ $P0["type"] = .CONTROL_RETURN
+ $P0["payload"] = payload
+
+ throw $P0
+.end
+
+.sub "_catch_untyped"
+ .local string desc
+ .local string payload
+
+ push_cached_eh catch
+ "_throw"(payload)
+ nok(1, "Exception not caught")
+ .return()
+
+ catch:
+ pop_eh
+ ok(1, desc)
+ .return()
+.end
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

No commit comments for this range

Something went wrong with that request. Please try again.