diff --git a/src/interpreter.c b/src/interpreter.c index 573b4f81f8ff4..00ea5a50934a6 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -351,6 +351,7 @@ static size_t eval_phi(jl_array_t *stmts, interpreter_state *s, size_t ns, size_ size_t from = s->ip; size_t ip = to; unsigned nphiblockstmts = 0; + unsigned last_phi = 0; for (ip = to; ip < ns; ip++) { jl_value_t *e = jl_array_ptr_ref(stmts, ip); if (!jl_is_phinode(e)) { @@ -361,9 +362,16 @@ static size_t eval_phi(jl_array_t *stmts, interpreter_state *s, size_t ns, size_ } // Everything else is allowed in the phi-block for implementation // convenience - fall through. + } else { + last_phi = nphiblockstmts + 1; } nphiblockstmts += 1; } + // Cut off the phi block at the last phi node. For global refs that are not + // actually in the phi block, we want to evaluate them in the regular interpreter + // loop instead to make sure exception state is set up properly in case they throw. + nphiblockstmts = last_phi; + ip = to + last_phi; if (nphiblockstmts) { jl_value_t **dest = &s->locals[jl_source_nslots(s->src) + to]; jl_value_t **phis; // = (jl_value_t**)alloca(sizeof(jl_value_t*) * nphiblockstmts); diff --git a/test/stacktraces.jl b/test/stacktraces.jl index 5b17a0ced4058..be035e31833d3 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -166,6 +166,22 @@ end @test bt[1].line == topline+4 end +# Accidental incorrect phi block computation in interpreter +global global_false_bool = false +let bt, topline = @__LINE__ + try + let + global read_write_global_bt_test, global_false_bool + if global_false_bool + end + (read_write_global_bt_test, (read_write_global_bt_test=2;)) + end + catch + bt = stacktrace(catch_backtrace()) + end + @test bt[1].line == topline+6 +end + # issue #28990 let bt try