diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 7085b87db9beb..dd3b10405fccf 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -368,7 +368,7 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet) handler_id = length(handlers) handler_at[pc + 1] = (handler_id, 0) push!(ip, pc + 1) - handler_at[l] = (handler_id, handler_id) + handler_at[l] = (0, handler_id) push!(ip, l) end end @@ -399,7 +399,10 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet) elseif isa(stmt, Expr) head = stmt.head if head === :enter - # Already set above + l = stmt.args[1]::Int + # We assigned a handler number above. Here we just merge that + # with out current handler information. + handler_at[l] = (cur_stacks[1], handler_at[l][2]) cur_stacks = (handler_at[pc´][1], cur_stacks[2]) elseif head === :leave l = 0 diff --git a/src/codegen.cpp b/src/codegen.cpp index 45b20e0044847..bd5572ce7be16 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8745,11 +8745,16 @@ static jl_llvm_functions_t sj->setCanReturnTwice(); Value *isz = ctx.builder.CreateICmpEQ(sj, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)); BasicBlock *tryblk = BasicBlock::Create(ctx.builder.getContext(), "try", f); + BasicBlock *catchpop = BasicBlock::Create(ctx.builder.getContext(), "catch_pop", f); BasicBlock *handlr = NULL; handlr = BB[lname]; workstack.push_back(lname - 1); come_from_bb[cursor + 1] = ctx.builder.GetInsertBlock(); - ctx.builder.CreateCondBr(isz, tryblk, handlr); + ctx.builder.CreateCondBr(isz, tryblk, catchpop); + ctx.builder.SetInsertPoint(catchpop); + ctx.builder.CreateCall(prepare_call(jlleave_func), + ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 1)); + ctx.builder.CreateBr(handlr); ctx.builder.SetInsertPoint(tryblk); } else { diff --git a/src/interpreter.c b/src/interpreter.c index d9536ca512889..7f8bd236819d5 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -550,15 +550,17 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, s->locals[jl_source_nslots(s->src) + ip] = jl_box_ulong(jl_excstack_state()); if (!jl_setjmp(__eh.eh_ctx, 1)) { return eval_body(stmts, s, next_ip, toplevel); - } - else if (s->continue_at) { // means we reached a :leave expression - ip = s->continue_at; - s->continue_at = 0; - continue; - } - else { // a real exception - ip = catch_ip; - continue; + } else { + jl_eh_restore_state(&__eh); + if (s->continue_at) { // means we reached a :leave expression + ip = s->continue_at; + s->continue_at = 0; + continue; + } + else { // a real exception + ip = catch_ip; + continue; + } } } else if (head == jl_leave_sym) { @@ -575,11 +577,11 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip, } if (hand_n_leave > 0) { assert(hand_n_leave > 0); - // equivalent to jl_pop_handler(hand_n_leave), but retaining eh for longjmp: + // equivalent to jl_pop_handler(hand_n_leave), longjmping + // to the :enter code above instead, which handles cleanup jl_handler_t *eh = ct->eh; while (--hand_n_leave > 0) eh = eh->prev; - jl_eh_restore_state(eh); // leave happens during normal control flow, but we must // longjmp to pop the eval_body call for each enter. s->continue_at = next_ip; diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 2937f31ecc0f2..4dd7735776315 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -4755,9 +4755,9 @@ f(x) = yt(x) (let ((v3 (compile (cadddr e) break-labels value tail))) ;; emit else block code (if val (emit-assignment val v3))) (if endl (emit `(goto ,endl))))) - ;; emit either catch or finally block + ;; emit either catch or finally block. A combined try/catch/finally block was split into + ;; separate trycatch and tryfinally blocks earlier. (mark-label catch) - (emit `(leave ,handler-token)) (if finally (begin (enter-finally-block '(call (top rethrow)) #f) ;; enter block via exception (mark-label endl) ;; non-exceptional control flow enters here diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 88bd4d8fba007..f0a01eba61405 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -4416,7 +4416,7 @@ g41908() = f41908(Any[1][1]) # issue #42022 let x = Tuple{Int,Any}[ #= 1=# (0, Expr(:(=), Core.SlotNumber(3), 1)) - #= 2=# (0, Expr(:enter, 18)) + #= 2=# (0, Expr(:enter, 17)) #= 3=# (2, Expr(:(=), Core.SlotNumber(3), 2.0)) #= 4=# (2, Expr(:enter, 12)) #= 5=# (4, Expr(:(=), Core.SlotNumber(3), '3')) @@ -4425,18 +4425,16 @@ let x = Tuple{Int,Any}[ #= 8=# (0, Core.ReturnNode(1)) #= 9=# (4, Expr(:call, GlobalRef(Main, :throw))) #=10=# (4, Expr(:leave, Core.SSAValue(4))) - #=11=# (2, Core.GotoNode(16)) - #=12=# (4, Expr(:leave, Core.SSAValue(4))) - #=13=# (2, Expr(:(=), Core.SlotNumber(4), Expr(:the_exception))) - #=14=# (2, Expr(:call, GlobalRef(Main, :rethrow))) - #=15=# (2, Expr(:pop_exception, Core.SSAValue(4))) - #=16=# (2, Expr(:leave, Core.SSAValue(2))) - #=17=# (0, Core.GotoNode(22)) - #=18=# (2, Expr(:leave, Core.SSAValue(2))) - #=19=# (0, Expr(:(=), Core.SlotNumber(5), Expr(:the_exception))) - #=20=# (0, nothing) - #=21=# (0, Expr(:pop_exception, Core.SSAValue(2))) - #=22=# (0, Core.ReturnNode(Core.SlotNumber(3))) + #=11=# (2, Core.GotoNode(15)) + #=12=# (2, Expr(:(=), Core.SlotNumber(4), Expr(:the_exception))) + #=13=# (2, Expr(:call, GlobalRef(Main, :rethrow))) + #=14=# (2, Expr(:pop_exception, Core.SSAValue(4))) + #=15=# (2, Expr(:leave, Core.SSAValue(2))) + #=16=# (0, Core.GotoNode(20)) + #=17=# (0, Expr(:(=), Core.SlotNumber(5), Expr(:the_exception))) + #=18=# (0, nothing) + #=19=# (0, Expr(:pop_exception, Core.SSAValue(2))) + #=20=# (0, Core.ReturnNode(Core.SlotNumber(3))) ] handler_at, handlers = Core.Compiler.compute_trycatch(last.(x), Core.Compiler.BitSet()) @test map(x->x[1] == 0 ? 0 : handlers[x[1]].enter_idx, handler_at) == first.(x) diff --git a/test/compiler/interpreter_exec.jl b/test/compiler/interpreter_exec.jl index 641656196c00d..47dc3778402bd 100644 --- a/test/compiler/interpreter_exec.jl +++ b/test/compiler/interpreter_exec.jl @@ -94,7 +94,6 @@ let m = Meta.@lower 1 + 1 # block 6 Core.PhiCNode(Any[Core.SSAValue(5), Core.SSAValue(7), Core.SSAValue(9)]), # NULL, :a, :b Core.PhiCNode(Any[Core.SSAValue(6)]), # NULL - Expr(:leave, Core.SSAValue(4)), # block 7 ReturnNode(Core.SSAValue(11)), ] diff --git a/test/show.jl b/test/show.jl index 899327d80b531..a2ed2bba31f50 100644 --- a/test/show.jl +++ b/test/show.jl @@ -2089,8 +2089,8 @@ let src = code_typed(my_fun28173, (Int,), debuginfo=:source)[1][1] end @test popfirst!(lines2) == " │ $(QuoteNode(2))" @test pop!(lines2) == " └─── \$(QuoteNode(4))" - @test pop!(lines1) == "18 └─── return %22" - @test pop!(lines2) == " │ return %22" + @test pop!(lines1) == "18 └─── return %21" + @test pop!(lines2) == " │ return %21" @test pop!(lines2) == "18 │ \$(QuoteNode(3))" @test lines1 == lines2