Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
2903-beam_ssa_bc_size-Don-t-break-try-catch-on-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2903-beam_ssa_bc_size-Don-t-break-try-catch-on-bad_genera.patch of Package erlang
From b958dece2f26e508c06282adcfa487e6e2455bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org> Date: Wed, 13 Jan 2021 16:08:19 +0100 Subject: [PATCH 3/8] beam_ssa_bc_size: Don't break try/catch on `bad_generator` All exceptions must be reflected in the control flow for try/catch optimization to work. --- lib/compiler/src/beam_ssa_bc_size.erl | 64 +++++++++++++++++++-------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/lib/compiler/src/beam_ssa_bc_size.erl b/lib/compiler/src/beam_ssa_bc_size.erl index 57318f2558..9af43f17d5 100644 --- a/lib/compiler/src/beam_ssa_bc_size.erl +++ b/lib/compiler/src/beam_ssa_bc_size.erl @@ -90,13 +90,19 @@ opt_blks([], _ParamInfo, _StMap, unchanged, _Count, _Acc) -> opt_writable(Bs0, L, Blk, Blks, ParamInfo, Count0, Acc0) -> case {Blk,Blks} of {#b_blk{last=#b_br{succ=Next,fail=Next}}, - [{Next,#b_blk{is=[#b_set{op=call,args=[_|Args],dst=Dst}=Call|_]}}|_]} -> + [{Next,#b_blk{is=[#b_set{op=call,args=[_|Args],dst=Dst}=Call|_], + last=CallLast}}|_]} -> ensure_not_match_context(Call, ParamInfo), + ArgTypes = maps:from_list([{Arg,{arg,Arg}} || Arg <- Args]), Bs = maps:merge(ArgTypes, Bs0), Result = map_get(Dst, call_size_func(Call, Bs)), {Expr,Annos} = make_expr_tree(Result), - cg_size_calc(Expr, L, Blk, Annos, Count0, Acc0); + + %% Note that we pass the generator call's terminator: should we + %% need to raise a `bad_generator` exception, it needs to fail in + %% the same manner as the generator itself. + cg_size_calc(Expr, L, Blk, CallLast, Annos, Count0, Acc0); {_,_} -> throw(not_possible) end. @@ -514,20 +520,24 @@ literal_expr_args([], Acc) -> %%% bytes to allocate for the writable binary. %%% -cg_size_calc(Expr, L, #b_blk{is=Is0}=Blk0, Annos, Count0, Acc0) -> +cg_size_calc(Expr, L, #b_blk{is=Is0}=Blk0, CallLast, Annos, Count0, Acc0) -> [InitWr] = Is0, FailBlk0 = [], - {Acc1,Alloc,NextBlk,FailBlk,Count} = cg_size_calc_1(L, Expr, Annos, FailBlk0, Count0, Acc0), + {Acc1,Alloc,NextBlk,FailBlk,Count} = cg_size_calc_1(L, Expr, Annos, + CallLast, FailBlk0, + Count0, Acc0), Is = [InitWr#b_set{args=[Alloc]}], Blk = Blk0#b_blk{is=Is}, Acc = [{NextBlk,Blk}|FailBlk++Acc1], {Acc,Count}. -cg_size_calc_1(L, #b_literal{}=Alloc, _Annos, FailBlk, Count, Acc) -> +cg_size_calc_1(L, #b_literal{}=Alloc, _Annos, _CallLast, FailBlk, Count, Acc) -> {Acc,Alloc,L,FailBlk,Count}; -cg_size_calc_1(L0, {Op0,Args0}, Annos, FailBlk0, Count0, Acc0) -> - {Args,Acc1,L,FailBlk1,Count1} = cg_atomic_args(Args0, L0, Annos, FailBlk0, Count0, Acc0, []), - {BadGenL,FailBlk,Count2} = cg_bad_generator(Args, Annos, FailBlk1, Count1), +cg_size_calc_1(L0, {Op0,Args0}, Annos, CallLast, FailBlk0, Count0, Acc0) -> + {Args,Acc1,L,FailBlk1,Count1} = cg_atomic_args(Args0, L0, Annos, CallLast, + FailBlk0, Count0, Acc0, []), + {BadGenL,FailBlk,Count2} = cg_bad_generator(Args, Annos, CallLast, + FailBlk1, Count1), {Dst,Count3} = new_var('@ssa_tmp', Count2), case Op0 of {safe,Op} -> @@ -551,20 +561,20 @@ cg_size_calc_1(L0, {Op0,Args0}, Annos, FailBlk0, Count0, Acc0) -> {Acc,Dst,NextBlkL,FailBlk,Count} end. -cg_bad_generator([Arg|_], Annos, FailBlk, Count) -> +cg_bad_generator([Arg|_], Annos, CallLast, FailBlk, Count) -> case Annos of #{Arg := Anno} -> - cg_bad_generator_1(Anno, Arg, FailBlk, Count); + cg_bad_generator_1(Anno, Arg, CallLast, FailBlk, Count); #{} -> case FailBlk of [{L,_}|_] -> {L,FailBlk,Count}; [] -> - cg_bad_generator_1(#{}, Arg, FailBlk, Count) + cg_bad_generator_1(#{}, Arg, CallLast, FailBlk, Count) end end. -cg_bad_generator_1(Anno, Arg, FailBlk, Count0) -> +cg_bad_generator_1(Anno, Arg, CallLast, FailBlk, Count0) -> {L,Count1} = new_block(Count0), {TupleDst,Count2} = new_var('@ssa_tuple', Count1), {Ret,Count3} = new_var('@ssa_ret', Count2), @@ -576,7 +586,19 @@ cg_bad_generator_1(Anno, Arg, FailBlk, Count0) -> dst=TupleDst}, CallI = #b_set{anno=Anno,op=call,args=[MFA,TupleDst],dst=Ret}, Is = [TupleI,CallI], - Blk = #b_blk{is=Is,last=#b_ret{arg=Ret}}, + + %% When the generator is called within try/catch, the `bad_generator` call + %% must refer to the same landing pad or else we'll break optimizations + %% that assume exceptions are always reflected in the control flow. + Last = case CallLast of + #b_br{fail=CatchLbl} when CatchLbl =/= ?EXCEPTION_BLOCK -> + #b_br{bool=#b_literal{val=true}, + succ=CatchLbl,fail=CatchLbl}; + _ -> + #b_ret{arg=Ret} + end, + + Blk = #b_blk{is=Is,last=Last}, {L,[{L,Blk}|FailBlk],Count3}. cg_succeeded(#b_set{dst=OpDst}=I, Succ, Fail, Count0) -> @@ -588,20 +610,24 @@ cg_succeeded(#b_set{dst=OpDst}=I, Succ, Fail, Count0) -> cg_br(Target) -> #b_br{bool=#b_literal{val=true},succ=Target,fail=Target}. -cg_atomic_args([A|As], L, Annos, FailBlk0, Count0, BlkAcc0, Acc) -> +cg_atomic_args([A|As], L, Annos, CallLast, FailBlk0, Count0, BlkAcc0, Acc) -> case A of #b_literal{} -> - cg_atomic_args(As, L, Annos, FailBlk0, Count0, BlkAcc0, [A|Acc]); + cg_atomic_args(As, L, Annos, CallLast, FailBlk0, + Count0, BlkAcc0, [A|Acc]); #b_var{} -> - cg_atomic_args(As, L, Annos, FailBlk0, Count0, BlkAcc0, [A|Acc]); + cg_atomic_args(As, L, Annos, CallLast, FailBlk0, + Count0, BlkAcc0, [A|Acc]); none -> throw(not_possible); _ -> {BlkAcc,Var,NextBlk,FailBlk,Count} = - cg_size_calc_1(L, A, Annos, FailBlk0, Count0, BlkAcc0), - cg_atomic_args(As, NextBlk, Annos, FailBlk, Count, BlkAcc, [Var|Acc]) + cg_size_calc_1(L, A, Annos, CallLast, FailBlk0, + Count0, BlkAcc0), + cg_atomic_args(As, NextBlk, Annos, CallLast, FailBlk, + Count, BlkAcc, [Var|Acc]) end; -cg_atomic_args([], NextBlk, _Annos, FailBlk, Count, BlkAcc, Acc) -> +cg_atomic_args([], NextBlk, _Annos, _CallLast, FailBlk, Count, BlkAcc, Acc) -> {reverse(Acc),BlkAcc,NextBlk,FailBlk,Count}. new_var(Base, Count) -> -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor