Skip to content

Commit

Permalink
Implement payload throw/handler support.
Browse files Browse the repository at this point in the history
To more effciently provide for implementing `return` using control
exceptions instead of the lexotic mechanism.
  • Loading branch information
jnthn committed Jun 2, 2016
1 parent 1339332 commit 882c50d
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 187 deletions.
8 changes: 4 additions & 4 deletions lib/MAST/Nodes.nqp
Expand Up @@ -619,9 +619,9 @@ class MAST::Annotated is MAST::Node {

# Handler constants.
module HandlerAction {
our $unwind_and_goto := 0;
our $unwind_and_goto_obj := 1;
our $invoke_and_we'll_see := 2;
our $unwind_and_goto := 0;
our $unwind_and_goto_with_payload := 1;
our $invoke_and_we'll_see := 2;
}

# Category constants.
Expand Down Expand Up @@ -672,7 +672,7 @@ class MAST::HandlerScope is MAST::Node {
}
}
elsif $action != $HandlerAction::unwind_and_goto &&
$action != $HandlerAction::unwind_and_goto_obj {
$action != $HandlerAction::unwind_and_goto_with_payload {
nqp::die("Unknown handler action");
}
if $category_mask +& $HandlerCategory::labeled {
Expand Down
233 changes: 126 additions & 107 deletions lib/MAST/Ops.nqp
Expand Up @@ -745,65 +745,68 @@ BEGIN {
1848,
1849,
1851,
1853,
1853,
1855,
1854,
1857,
1858,
1860,
1863,
1866,
1869,
1871,
1860,
1862,
1864,
1867,
1870,
1873,
1875,
1877,
1879,
1876,
1878,
1880,
1882,
1885,
1888,
1891,
1884,
1886,
1889,
1892,
1894,
1895,
1898,
1899,
1901,
1904,
1907,
1910,
1913,
1916,
1919,
1922,
1925,
1928,
1931,
1934,
1937,
1940,
1943,
1946,
1905,
1908,
1911,
1914,
1917,
1920,
1923,
1926,
1929,
1932,
1935,
1938,
1941,
1944,
1947,
1950,
1954,
1953,
1957,
1960,
1963,
1966,
1969,
1972,
1975,
1978,
1981,
1984,
1987,
1961,
1964,
1967,
1970,
1973,
1976,
1979,
1982,
1985,
1988,
1990,
1992,
1994,
1994,
1991,
1994,
1995,
1996,
1996,
1997);
1997,
1999,
2001,
2001,
2001,
2002,
2003,
2003,
2004);
MAST::Ops.WHO<@counts> := nqp::list_i(0,
2,
2,
Expand Down Expand Up @@ -1545,6 +1548,9 @@ BEGIN {
2,
1,
2,
3,
3,
1,
2,
0,
2,
Expand Down Expand Up @@ -3456,6 +3462,13 @@ BEGIN {
65,
65,
57,
66,
32,
65,
66,
32,
65,
66,
65,
16,
65,
Expand Down Expand Up @@ -4345,66 +4358,69 @@ BEGIN {
'setdebugtypename', 738,
'loadbytecodebuffer', 739,
'loadbytecodefh', 740,
'sp_log', 741,
'sp_osrfinalize', 742,
'sp_guardconc', 743,
'sp_guardtype', 744,
'sp_guardcontconc', 745,
'sp_guardconttype', 746,
'sp_guardrwconc', 747,
'sp_guardrwtype', 748,
'sp_getarg_o', 749,
'sp_getarg_i', 750,
'sp_getarg_n', 751,
'sp_getarg_s', 752,
'sp_fastinvoke_v', 753,
'sp_fastinvoke_i', 754,
'sp_fastinvoke_n', 755,
'sp_fastinvoke_s', 756,
'sp_fastinvoke_o', 757,
'sp_namedarg_used', 758,
'sp_getspeshslot', 759,
'sp_findmeth', 760,
'sp_fastcreate', 761,
'sp_get_o', 762,
'sp_get_i64', 763,
'sp_get_i32', 764,
'sp_get_i16', 765,
'sp_get_i8', 766,
'sp_get_n', 767,
'sp_get_s', 768,
'sp_bind_o', 769,
'sp_bind_i64', 770,
'sp_bind_i32', 771,
'sp_bind_i16', 772,
'sp_bind_i8', 773,
'sp_bind_n', 774,
'sp_bind_s', 775,
'sp_p6oget_o', 776,
'sp_p6ogetvt_o', 777,
'sp_p6ogetvc_o', 778,
'sp_p6oget_i', 779,
'sp_p6oget_n', 780,
'sp_p6oget_s', 781,
'sp_p6obind_o', 782,
'sp_p6obind_i', 783,
'sp_p6obind_n', 784,
'sp_p6obind_s', 785,
'sp_deref_get_i64', 786,
'sp_deref_get_n', 787,
'sp_deref_bind_i64', 788,
'sp_deref_bind_n', 789,
'sp_jit_enter', 790,
'sp_boolify_iter', 791,
'sp_boolify_iter_arr', 792,
'sp_boolify_iter_hash', 793,
'prof_enter', 794,
'prof_enterspesh', 795,
'prof_enterinline', 796,
'prof_enternative', 797,
'prof_exit', 798,
'prof_allocated', 799,
'ctw_check', 800);
'throwpayloadlex', 741,
'throwpayloadlexcaller', 742,
'lastexpayload', 743,
'sp_log', 744,
'sp_osrfinalize', 745,
'sp_guardconc', 746,
'sp_guardtype', 747,
'sp_guardcontconc', 748,
'sp_guardconttype', 749,
'sp_guardrwconc', 750,
'sp_guardrwtype', 751,
'sp_getarg_o', 752,
'sp_getarg_i', 753,
'sp_getarg_n', 754,
'sp_getarg_s', 755,
'sp_fastinvoke_v', 756,
'sp_fastinvoke_i', 757,
'sp_fastinvoke_n', 758,
'sp_fastinvoke_s', 759,
'sp_fastinvoke_o', 760,
'sp_namedarg_used', 761,
'sp_getspeshslot', 762,
'sp_findmeth', 763,
'sp_fastcreate', 764,
'sp_get_o', 765,
'sp_get_i64', 766,
'sp_get_i32', 767,
'sp_get_i16', 768,
'sp_get_i8', 769,
'sp_get_n', 770,
'sp_get_s', 771,
'sp_bind_o', 772,
'sp_bind_i64', 773,
'sp_bind_i32', 774,
'sp_bind_i16', 775,
'sp_bind_i8', 776,
'sp_bind_n', 777,
'sp_bind_s', 778,
'sp_p6oget_o', 779,
'sp_p6ogetvt_o', 780,
'sp_p6ogetvc_o', 781,
'sp_p6oget_i', 782,
'sp_p6oget_n', 783,
'sp_p6oget_s', 784,
'sp_p6obind_o', 785,
'sp_p6obind_i', 786,
'sp_p6obind_n', 787,
'sp_p6obind_s', 788,
'sp_deref_get_i64', 789,
'sp_deref_get_n', 790,
'sp_deref_bind_i64', 791,
'sp_deref_bind_n', 792,
'sp_jit_enter', 793,
'sp_boolify_iter', 794,
'sp_boolify_iter_arr', 795,
'sp_boolify_iter_hash', 796,
'prof_enter', 797,
'prof_enterspesh', 798,
'prof_enterinline', 799,
'prof_enternative', 800,
'prof_exit', 801,
'prof_allocated', 802,
'ctw_check', 803);
MAST::Ops.WHO<@names> := nqp::list_s('no_op',
'const_i8',
'const_i16',
Expand Down Expand Up @@ -5146,6 +5162,9 @@ BEGIN {
'setdebugtypename',
'loadbytecodebuffer',
'loadbytecodefh',
'throwpayloadlex',
'throwpayloadlexcaller',
'lastexpayload',
'sp_log',
'sp_osrfinalize',
'sp_guardconc',
Expand Down
34 changes: 28 additions & 6 deletions src/core/exceptions.c
Expand Up @@ -171,8 +171,18 @@ static LocatedHandler search_for_handler_from(MVMThreadContext *tc, MVMFrame *f,
* parameter; if ex_obj is passed, the category is not used). */
static void unwind_after_handler(MVMThreadContext *tc, void *sr_data);
static void cleanup_active_handler(MVMThreadContext *tc, void *sr_data);
static void run_handler(MVMThreadContext *tc, LocatedHandler lh, MVMObject *ex_obj, MVMuint32 category) {
static void run_handler(MVMThreadContext *tc, LocatedHandler lh, MVMObject *ex_obj,
MVMuint32 category, MVMObject *payload) {
switch (lh.handler->action) {
case MVM_EX_ACTION_GOTO_WITH_PAYLOAD:
if (payload)
tc->last_payload = payload;
else if (ex_obj)
tc->last_payload = ((MVMException *)ex_obj)->body.payload;
else
tc->last_payload = tc->instance->VMNull;
/* Deliberate fallthrough to unwind below. */

case MVM_EX_ACTION_GOTO:
if (lh.jit_handler) {
void **labels = lh.frame->spesh_cand->jitcode->labels;
Expand All @@ -194,10 +204,13 @@ static void run_handler(MVMThreadContext *tc, LocatedHandler lh, MVMObject *ex_o
if (ex_obj == NULL) {
MVMROOT(tc, cur_frame, {
MVMROOT(tc, lh.frame, {
MVMROOT(tc, payload, {
ex_obj = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTException);
});
});
});
((MVMException *)ex_obj)->body.category = category;
MVM_ASSIGN_REF(tc, &(ex_obj->header), ((MVMException *)ex_obj)->body.payload, payload);
}

/* Find frame to invoke. */
Expand Down Expand Up @@ -497,7 +510,7 @@ void MVM_exception_throwcat(MVMThreadContext *tc, MVMuint8 mode, MVMuint32 cat,
LocatedHandler lh = search_for_handler_from(tc, tc->cur_frame, mode, cat, NULL);
if (lh.frame == NULL)
panic_unhandled_cat(tc, cat);
run_handler(tc, lh, NULL, cat);
run_handler(tc, lh, NULL, cat, NULL);
}

void MVM_exception_die(MVMThreadContext *tc, MVMString *str, MVMRegister *rr) {
Expand Down Expand Up @@ -549,7 +562,16 @@ void MVM_exception_throwobj(MVMThreadContext *tc, MVMuint8 mode, MVMObject *ex_o
tc->cur_frame->keep_caller = 1;
}

run_handler(tc, lh, ex_obj, 0);
run_handler(tc, lh, ex_obj, 0, NULL);
}

/* Throws an exception of the specified category and with the specified payload.
* If a goto or payload handler exists, then no exception object will be created. */
void MVM_exception_throwpayload(MVMThreadContext *tc, MVMuint8 mode, MVMuint32 cat, MVMObject *payload, MVMRegister *resume_result) {
LocatedHandler lh = search_for_handler_from(tc, tc->cur_frame, mode, cat, NULL);
if (lh.frame == NULL)
panic_unhandled_cat(tc, cat);
run_handler(tc, lh, NULL, cat, payload);
}

void MVM_exception_resume(MVMThreadContext *tc, MVMObject *ex_obj) {
Expand All @@ -561,7 +583,7 @@ void MVM_exception_resume(MVMThreadContext *tc, MVMObject *ex_obj) {
ex = (MVMException *)ex_obj;
else
MVM_exception_throw_adhoc(tc, "Can only resume an exception object");

/* Check that everything is in place to do the resumption. */
if (!ex->body.resume_addr)
MVM_exception_throw_adhoc(tc, "This exception is not resumable");
Expand Down Expand Up @@ -692,7 +714,7 @@ void MVM_exception_gotolexotic(MVMThreadContext *tc, MVMint32 handler_idx, MVMSt
lh.jit_handler = &(f->spesh_cand->jitcode->handlers[handler_idx]);
else
lh.jit_handler = NULL;
run_handler(tc, lh, NULL, MVM_EX_CAT_RETURN);
run_handler(tc, lh, NULL, MVM_EX_CAT_RETURN, NULL);
}
else {
MVM_exception_throw_adhoc(tc, "Too late to invoke lexotic return");
Expand Down Expand Up @@ -822,7 +844,7 @@ void MVM_exception_throw_adhoc_free_va(MVMThreadContext *tc, char **waste, const

/* Run the handler, which doesn't actually run it but rather sets up the
* interpreter so that when we return to it, we'll be at the handler. */
run_handler(tc, lh, (MVMObject *)ex, MVM_EX_CAT_CATCH);
run_handler(tc, lh, (MVMObject *)ex, MVM_EX_CAT_CATCH, NULL);

/* Clear any C stack temporaries that code may have pushed before throwing
* the exception, and release any needed mutex. */
Expand Down

0 comments on commit 882c50d

Please sign in to comment.