@@ -59,23 +59,24 @@ extern "C" {
5959#ifdef IMPL_EXECUTE_LOOP
6060
6161#if AVM_NO_JIT
62- #define SET_ERROR (error_type_atom ) \
63- x_regs[0] = ERROR_ATOM; \
64- x_regs[1] = error_type_atom; \
65- x_regs[2] = stacktrace_create_raw(ctx, mod, pc - code, ERROR_ATOM);
62+ #define SET_ERROR (error_type_atom ) \
63+ ctx->exception_class = ERROR_ATOM; \
64+ ctx->exception_reason = error_type_atom; \
65+ ctx->exception_stacktrace = stacktrace_create_raw(ctx, mod, pc - code, ERROR_ATOM);
6666#elif AVM_NO_EMU
67- #define SET_ERROR (error_type_atom ) \
68- x_regs[0] = ERROR_ATOM; \
69- x_regs[1] = error_type_atom; \
70- x_regs[2] = stacktrace_create_raw(ctx, mod, (const uint8_t *) native_pc - (const uint8_t *) mod->native_code, ERROR_ATOM);
67+ #define SET_ERROR (error_type_atom ) \
68+ ctx->exception_class = ERROR_ATOM; \
69+ ctx->exception_reason = error_type_atom; \
70+ ctx->exception_stacktrace = stacktrace_create_raw(ctx, mod, (const uint8_t *) native_pc - (const uint8_t *) mod->native_code, ERROR_ATOM);
7171#else
72- #define SET_ERROR (error_type_atom ) \
73- x_regs[0] = ERROR_ATOM; \
74- x_regs[1] = error_type_atom; \
75- if (mod->native_code) { \
76- x_regs[2] = stacktrace_create_raw(ctx, mod, (const uint8_t *) native_pc - (const uint8_t *) mod->native_code, ERROR_ATOM); \
77- } else { \
78- x_regs[2] = stacktrace_create_raw(ctx, mod, pc - code, ERROR_ATOM); \
72+ #define SET_ERROR (error_type_atom ) \
73+ ctx->exception_class = ERROR_ATOM; \
74+ ctx->exception_reason = error_type_atom; \
75+ if (mod->native_code) { \
76+ ctx->exception_stacktrace = stacktrace_create_raw(ctx, mod, \
77+ (const uint8_t *) native_pc - (const uint8_t *) mod->native_code, ERROR_ATOM); \
78+ } else { \
79+ ctx->exception_stacktrace = stacktrace_create_raw(ctx, mod, pc - code, ERROR_ATOM); \
7980 }
8081#endif
8182
@@ -1312,7 +1313,7 @@ static void destroy_extended_registers(Context *ctx, unsigned int live)
13121313#endif
13131314
13141315#define HANDLE_ERROR () \
1315- x_regs[2] = stacktrace_create_raw(ctx, mod, pc - code, x_regs[0] ); \
1316+ ctx->exception_stacktrace = stacktrace_create_raw(ctx, mod, pc - code, ctx->exception_class ); \
13161317 goto handle_error;
13171318
13181319#define VERIFY_IS_INTEGER (t , opcode_name , label ) \
@@ -3973,6 +3974,9 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
39733974 #ifdef IMPL_EXECUTE_LOOP
39743975 // clears the catch value on stack
39753976 WRITE_REGISTER (dreg , term_nil ());
3977+ ctx -> x [0 ] = ctx -> exception_class ;
3978+ ctx -> x [1 ] = ctx -> exception_reason ;
3979+ ctx -> x [2 ] = ctx -> exception_stacktrace ;
39763980 #endif
39773981 break ;
39783982 }
@@ -4020,9 +4024,9 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
40204024
40214025 #ifdef IMPL_EXECUTE_LOOP
40224026 TRACE ("raise/2 stacktrace=0x%" TERM_X_FMT " exc_value=0x%" TERM_X_FMT "\n" , stacktrace , exc_value );
4023- x_regs [ 0 ] = stacktrace_exception_class (stacktrace );
4024- x_regs [ 1 ] = exc_value ;
4025- x_regs [ 2 ] = stacktrace_create_raw (ctx , mod , saved_pc - code , x_regs [ 0 ] );
4027+ ctx -> exception_class = stacktrace_exception_class (stacktrace );
4028+ ctx -> exception_reason = exc_value ;
4029+ ctx -> exception_stacktrace = stacktrace_create_raw (ctx , mod , saved_pc - code , ctx -> exception_class );
40264030 goto handle_error ;
40274031 #endif
40284032
@@ -4053,19 +4057,20 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
40534057 #ifdef IMPL_EXECUTE_LOOP
40544058 WRITE_REGISTER (dreg , term_nil ());
40554059 // C.f. https://www.erlang.org/doc/reference_manual/expressions.html#catch-and-throw
4056- switch (term_to_atom_index (x_regs [ 0 ] )) {
4060+ switch (term_to_atom_index (ctx -> exception_class )) {
40574061 case THROW_ATOM_INDEX :
4058- x_regs [0 ] = x_regs [ 1 ] ;
4062+ x_regs [0 ] = ctx -> exception_reason ;
40594063 break ;
40604064
40614065 case ERROR_ATOM_INDEX : {
4066+ x_regs [2 ] = ctx -> exception_stacktrace ;
40624067 x_regs [2 ] = stacktrace_build (ctx , & x_regs [2 ], 3 );
40634068 // MEMORY_CAN_SHRINK because catch_end is classified as gc in beam_ssa_codegen.erl
40644069 if (UNLIKELY (memory_ensure_free_with_roots (ctx , TUPLE_SIZE (2 ) * 2 , 2 , x_regs + 1 , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
40654070 RAISE_ERROR (OUT_OF_MEMORY_ATOM );
40664071 }
40674072 term reason_tuple = term_alloc_tuple (2 , & ctx -> heap );
4068- term_put_tuple_element (reason_tuple , 0 , x_regs [ 1 ] );
4073+ term_put_tuple_element (reason_tuple , 0 , ctx -> exception_reason );
40694074 term_put_tuple_element (reason_tuple , 1 , x_regs [2 ]);
40704075 term exit_tuple = term_alloc_tuple (2 , & ctx -> heap );
40714076 term_put_tuple_element (exit_tuple , 0 , EXIT_ATOM );
@@ -4081,7 +4086,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
40814086 }
40824087 term exit_tuple = term_alloc_tuple (2 , & ctx -> heap );
40834088 term_put_tuple_element (exit_tuple , 0 , EXIT_ATOM );
4084- term_put_tuple_element (exit_tuple , 1 , x_regs [ 1 ] );
4089+ term_put_tuple_element (exit_tuple , 1 , ctx -> exception_reason );
40854090 x_regs [0 ] = exit_tuple ;
40864091
40874092 break ;
@@ -6569,9 +6574,8 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
65696574 TRACE ("build_stacktrace/0\n" );
65706575
65716576 #ifdef IMPL_EXECUTE_LOOP
6572-
6577+ x_regs [ 0 ] = ctx -> exception_stacktrace ;
65736578 x_regs [0 ] = stacktrace_build (ctx , & x_regs [0 ], 1 );
6574-
65756579 #endif
65766580 break ;
65776581 }
@@ -6590,6 +6594,9 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
65906594 ex_class != THROW_ATOM )) {
65916595 x_regs [0 ] = BADARG_ATOM ;
65926596 } else {
6597+ ctx -> exception_class = x_regs [0 ];
6598+ ctx -> exception_reason = x_regs [1 ];
6599+ ctx -> exception_stacktrace = x_regs [2 ];
65936600 goto handle_error ;
65946601 }
65956602 #endif
@@ -7567,15 +7574,15 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
75677574
75687575#ifdef AVM_PRINT_PROCESS_CRASH_DUMPS
75697576 // Do not print crash dump if reason is normal or shutdown.
7570- if (x_regs [ 0 ] != LOWERCASE_EXIT_ATOM || (x_regs [ 1 ] != NORMAL_ATOM && x_regs [ 1 ] != SHUTDOWN_ATOM )) {
7577+ if (ctx -> exception_class != LOWERCASE_EXIT_ATOM || (ctx -> exception_reason != NORMAL_ATOM && ctx -> exception_reason != SHUTDOWN_ATOM )) {
75717578 context_dump (ctx );
75727579 }
75737580#endif
75747581
7575- if (x_regs [ 0 ] == LOWERCASE_EXIT_ATOM ) {
7576- ctx -> exit_reason = x_regs [ 1 ] ;
7582+ if (ctx -> exception_class == LOWERCASE_EXIT_ATOM ) {
7583+ ctx -> exit_reason = ctx -> exception_reason ;
75777584 } else {
7578- bool throw = ctx -> x [ 0 ] == THROW_ATOM ;
7585+ bool throw = ctx -> exception_class == THROW_ATOM ;
75797586
75807587 int exit_reason_tuple_size = (throw ? TUPLE_SIZE (2 ) : 0 ) + TUPLE_SIZE (2 );
75817588 if (memory_ensure_free_with_roots (ctx , exit_reason_tuple_size , 1 , x_regs + 1 , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK ) {
@@ -7585,10 +7592,10 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
75857592 if (throw ) {
75867593 error_term = term_alloc_tuple (2 , & ctx -> heap );
75877594 term_put_tuple_element (error_term , 0 , NOCATCH_ATOM );
7588- term_put_tuple_element (error_term , 1 , x_regs [ 1 ] );
7595+ term_put_tuple_element (error_term , 1 , ctx -> exception_reason );
75897596 } else {
75907597 // error
7591- error_term = x_regs [ 1 ] ;
7598+ error_term = ctx -> exception_reason ;
75927599 }
75937600
75947601 term exit_reason_tuple = term_alloc_tuple (2 , & ctx -> heap );
0 commit comments