@@ -1170,7 +1170,7 @@ static void destroy_extended_registers(Context *ctx, unsigned int live)
11701170#define PROCESS_MAYBE_TRAP_RETURN_VALUE (return_value ) \
11711171 if (term_is_invalid_term(return_value)) { \
11721172 if (UNLIKELY(!context_get_flags(ctx, Trap))) { \
1173- HANDLE_ERROR (); \
1173+ HANDLE_ERROR_MAYBE_STACKTRACE (); \
11741174 } else { \
11751175 SCHEDULE_WAIT(mod, pc); \
11761176 } \
@@ -1180,7 +1180,7 @@ static void destroy_extended_registers(Context *ctx, unsigned int live)
11801180 if (term_is_invalid_term(return_value)) { \
11811181 if (UNLIKELY(!context_get_flags(ctx, Trap))) { \
11821182 pc = rest_pc; \
1183- HANDLE_ERROR (); \
1183+ HANDLE_ERROR_MAYBE_STACKTRACE (); \
11841184 } else { \
11851185 SCHEDULE_WAIT(mod, pc); \
11861186 } \
@@ -1189,7 +1189,7 @@ static void destroy_extended_registers(Context *ctx, unsigned int live)
11891189#define PROCESS_MAYBE_TRAP_RETURN_VALUE_LAST (return_value ) \
11901190 if (term_is_invalid_term(return_value)) { \
11911191 if (UNLIKELY(!context_get_flags(ctx, Trap))) { \
1192- HANDLE_ERROR (); \
1192+ HANDLE_ERROR_MAYBE_STACKTRACE (); \
11931193 } else { \
11941194 DO_RETURN(); \
11951195 SCHEDULE_WAIT(mod, pc); \
@@ -1216,6 +1216,10 @@ static void destroy_extended_registers(Context *ctx, unsigned int live)
12161216 x_regs[2] = stacktrace_create_raw(ctx, mod, pc - code, x_regs[0]); \
12171217 goto handle_error;
12181218
1219+ #define HANDLE_ERROR_MAYBE_STACKTRACE () \
1220+ x_regs[2] = x_regs[2] == term_nil() ? stacktrace_create_raw(ctx, mod, pc - code, x_regs[0]) : x_regs[2]; \
1221+ goto handle_error;
1222+
12191223#define VERIFY_IS_INTEGER (t , opcode_name , label ) \
12201224 if (UNLIKELY(!term_is_integer(t))) { \
12211225 TRACE(opcode_name ": " #t " is not an integer\n"); \
@@ -3741,9 +3745,13 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
37413745
37423746 #ifdef IMPL_EXECUTE_LOOP
37433747 TRACE ("raise/2 stacktrace=0x%lx exc_value=0x%lx\n" , stacktrace , exc_value );
3744- x_regs [0 ] = stacktrace_exception_class (stacktrace );
3745- x_regs [1 ] = exc_value ;
3746- x_regs [2 ] = stacktrace_create_raw (ctx , mod , saved_pc - code , x_regs [0 ]);
3748+ if (stacktrace_is_built (stacktrace )) {
3749+ x_regs [2 ] = stacktrace ;
3750+ } else {
3751+ x_regs [0 ] = stacktrace_exception_class (stacktrace );
3752+ x_regs [1 ] = exc_value ;
3753+ x_regs [2 ] = stacktrace_create_raw (ctx , mod , saved_pc - code , x_regs [0 ]);
3754+ }
37473755 goto handle_error ;
37483756 #endif
37493757
@@ -3780,7 +3788,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
37803788 break ;
37813789
37823790 case ERROR_ATOM_INDEX : {
3783- x_regs [2 ] = stacktrace_build (ctx , & x_regs [2 ], 3 );
3791+ x_regs [2 ] = stacktrace_ensure_built (ctx , & x_regs [2 ], 3 );
37843792 // MEMORY_CAN_SHRINK because catch_end is classified as gc in beam_ssa_codegen.erl
37853793 if (UNLIKELY (memory_ensure_free_with_roots (ctx , TUPLE_SIZE (2 ) * 2 , 2 , x_regs + 1 , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
37863794 RAISE_ERROR (OUT_OF_MEMORY_ATOM );
@@ -6249,7 +6257,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
62496257
62506258 #ifdef IMPL_EXECUTE_LOOP
62516259
6252- x_regs [0 ] = stacktrace_build (ctx , & x_regs [0 ], 1 );
6260+ x_regs [0 ] = stacktrace_ensure_built (ctx , & x_regs [0 ], 1 );
62536261
62546262 #endif
62556263 break ;
0 commit comments