Skip to content

Commit ecf5329

Browse files
committed
Fix OP_RAISE: it must preserve stacktrace
Our OP_RAISE has been always wrong: it must use stacktrace argument, and behave like raise/3 NIF. Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent 2a46512 commit ecf5329

File tree

5 files changed

+41
-15
lines changed

5 files changed

+41
-15
lines changed

libs/jit/src/jit.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ first_pass(<<?OP_RAISE, Rest0/binary>>, MMod, MSt0, State0) ->
11651165
{MSt2, ExcValue, Rest2} = decode_compact_term(Rest1, MMod, MSt1, State0),
11661166
?TRACE("OP_RAISE ~p, ~p\n", [Stacktrace, ExcValue]),
11671167
MSt3 = MMod:call_primitive_last(MSt2, ?PRIM_RAISE, [
1168-
ctx, jit_state, offset, Stacktrace, ExcValue
1168+
ctx, jit_state, Stacktrace, ExcValue
11691169
]),
11701170
?ASSERT_ALL_NATIVE_FREE(MSt3),
11711171
first_pass(Rest2, MMod, MSt3, State0);

src/libAtomVM/jit.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,12 @@ static Context *jit_raise_error_tuple(Context *ctx, JITState *jit_state, int off
337337
return jit_handle_error(ctx, jit_state, 0);
338338
}
339339

340-
static Context *jit_raise(Context *ctx, JITState *jit_state, int offset, term stacktrace, term exc_value)
340+
static Context *jit_raise(Context *ctx, JITState *jit_state, term stacktrace, term exc_value)
341341
{
342-
TRACE("jit_raise: ctx->process_id = %" PRId32 ", offset = %d\n", ctx->process_id, offset);
342+
TRACE("jit_raise: ctx->process_id = %" PRId32 "\n", ctx->process_id);
343343
context_set_exception_class(ctx, stacktrace_exception_class(stacktrace));
344344
ctx->exception_reason = exc_value;
345-
ctx->exception_stacktrace
346-
= stacktrace_create_raw(ctx, jit_state->module, offset);
345+
ctx->exception_stacktrace = stacktrace;
347346
return jit_handle_error(ctx, jit_state, 0);
348347
}
349348

src/libAtomVM/jit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ struct ModuleNativeInterface
114114
void (*mailbox_next)(Context *ctx);
115115
void (*cancel_timeout)(Context *ctx);
116116
void (*clear_timeout_flag)(Context *ctx);
117-
Context *(*raise)(Context *ctx, JITState *jit_state, int offset, term stacktrace, term exc_value);
117+
Context *(*raise)(Context *ctx, JITState *jit_state, term stacktrace, term exc_value);
118118
Context *(*schedule_wait_cp)(Context *ctx, JITState *jit_state);
119119
Context *(*wait_timeout)(Context *ctx, JITState *jit_state, term timeout, int label);
120120
Context *(*wait_timeout_trap_handler)(Context *ctx, JITState *jit_state, int label);

src/libAtomVM/opcodesswitch.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4058,9 +4058,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
40584058
}
40594059

40604060
case OP_RAISE: {
4061-
#ifdef IMPL_EXECUTE_LOOP
4062-
const uint8_t *saved_pc = pc - 1;
4063-
#endif
40644061
term stacktrace;
40654062
DECODE_COMPACT_TERM(stacktrace, pc);
40664063
term exc_value;
@@ -4076,7 +4073,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
40764073
TRACE("raise/2 stacktrace=0x%" TERM_X_FMT " exc_value=0x%" TERM_X_FMT "\n", stacktrace, exc_value);
40774074
context_set_exception_class(ctx, stacktrace_exception_class(stacktrace));
40784075
ctx->exception_reason = exc_value;
4079-
ctx->exception_stacktrace = stacktrace_create_raw(ctx, mod, saved_pc - code);
4076+
ctx->exception_stacktrace = stacktrace;
40804077
goto handle_error;
40814078
#endif
40824079

tests/erlang_tests/test_reraise.erl

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@
2020

2121
-module(test_reraise).
2222

23-
-export([start/0]).
23+
-export([start/0, do_error/0]).
2424

2525
start() ->
2626
start(?OTP_RELEASE).
2727

2828
start(OTPVersion) when OTPVersion >= 23 ->
29+
test_reraise_raise_3_nif(),
30+
test_reraise_preserves_stacktrace(),
31+
0;
32+
start(_) ->
33+
0.
34+
35+
test_reraise_raise_3_nif() ->
2936
try
3037
reraise_reraiser:reraise_error()
3138
catch
@@ -38,7 +45,30 @@ start(OTPVersion) when OTPVersion >= 23 ->
3845
{reraise_reraiser, reraise_error, 0, _Meta2}
3946
| _Rest
4047
] = Stacktrace
41-
end,
42-
0;
43-
start(_) ->
44-
0.
48+
end.
49+
50+
test_reraise_preserves_stacktrace() ->
51+
try
52+
try
53+
?MODULE:do_error()
54+
catch
55+
throw:_ -> should_not_happen
56+
end
57+
catch
58+
error:my_error:ST ->
59+
case ST of
60+
L when is_list(L) ->
61+
true = has_do_error(L),
62+
ok;
63+
_ ->
64+
%% Stacktraces disabled
65+
ok
66+
end
67+
end.
68+
69+
do_error() ->
70+
erlang:error(my_error).
71+
72+
has_do_error([{?MODULE, do_error, _, _} | _]) -> true;
73+
has_do_error([_ | T]) -> has_do_error(T);
74+
has_do_error([]) -> false.

0 commit comments

Comments
 (0)