diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compiler/src/beam_except.erl | 12 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_opt.erl | 8 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_type.erl | 24 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 16 | ||||
-rw-r--r-- | lib/stdlib/doc/src/ets.xml | 25 |
5 files changed, 65 insertions, 20 deletions
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl index 49bfb5606f..26b193a35b 100644 --- a/lib/compiler/src/beam_except.erl +++ b/lib/compiler/src/beam_except.erl @@ -79,13 +79,15 @@ translate_1(Ar, I, Is, #st{arity=Arity}=St, [{line,_}=Line|Acc1]=Acc0) -> no -> translate(Is, St, [I|Acc0]); {yes,function_clause,Acc2} -> - case {Line,St} of - {{line,Loc},#st{lbl=Fi,loc=Loc}} -> + case {Is,Line,St} of + {[return|_],{line,Loc},#st{lbl=Fi,loc=Loc}} -> Instr = {jump,{f,Fi}}, translate(Is, St, [Instr|Acc2]); - {_,_} -> - %% This must be "error(function_clause, Args)" in - %% the Erlang source code or a fun. Don't translate. + {_,_,_} -> + %% Not a call_only instruction, or not the same + %% location information as in in the line instruction + %% before the func_info instruction. Not safe + %% to translate to a jump. translate(Is, St, [I|Acc0]) end; {yes,Instr,Acc2} -> diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index aa94d8d671..e528bb4dfb 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -79,11 +79,9 @@ module(Module, Opts) -> {ok, finish(Module, StMap)}. phase([FuncId | Ids], Ps, StMap, FuncDb0) -> - try - {St, FuncDb} = - compile:run_sub_passes(Ps, {map_get(FuncId, StMap), FuncDb0}), - - phase(Ids, Ps, StMap#{ FuncId => St }, FuncDb) + try compile:run_sub_passes(Ps, {map_get(FuncId, StMap), FuncDb0}) of + {St, FuncDb} -> + phase(Ids, Ps, StMap#{ FuncId => St }, FuncDb) catch Class:Error:Stack -> #b_local{name=Name,arity=Arity} = FuncId, diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 38ea5e6914..8bd6772ac5 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -1072,15 +1072,23 @@ simplify_not(#b_br{bool=#b_var{}=V,succ=Succ,fail=Fail}=Br0, Ts, Ds) -> %%% %%% Calculate the set of variables that are only used once in the -%%% block that they are defined in. That will allow us to discard type -%%% information for variables that will never be referenced by the -%%% successor blocks, potentially improving compilation times. +%%% terminator of the block that defines them. That will allow us to +%%% discard type information for variables that will never be +%%% referenced by the successor blocks, potentially improving +%%% compilation times. %%% used_once(Linear, Args) -> Map0 = used_once_1(reverse(Linear), #{}), Map = maps:without(Args, Map0), - cerl_sets:from_list(maps:keys(Map)). + Used0 = cerl_sets:from_list(maps:keys(Map)), + Used1 = used_in_terminators(Linear, []), + cerl_sets:intersection(Used0, Used1). + +used_in_terminators([{_,#b_blk{last=Last}}|Bs], Acc) -> + used_in_terminators(Bs, beam_ssa:used(Last) ++ Acc); +used_in_terminators([], Acc) -> + cerl_sets:from_list(Acc). used_once_1([{L,#b_blk{is=Is,last=Last}}|Bs], Uses0) -> Uses = used_once_2([Last|reverse(Is)], L, Uses0), @@ -1177,7 +1185,7 @@ get_type(#b_literal{val=Val}, _Ts) -> %% failed and that L is not 'cons'. 'cons' can be subtracted from the %% previously known type for L and the result put in FailTypes. -infer_types(#b_var{}=V, Ts, #d{ds=Ds,once=Once}) -> +infer_types(#b_var{}=V, Ts, #d{ds=Ds}) -> #{V:=#b_set{op=Op,args=Args}} = Ds, Types0 = infer_type(Op, Args, Ds), @@ -1195,11 +1203,7 @@ infer_types(#b_var{}=V, Ts, #d{ds=Ds,once=Once}) -> is_singleton_type(T) end, EqTypes0), - %% Don't bother updating the types for variables that - %% are never used again. - Types2 = Types1 ++ Types0, - Types = [P || {InfV,_}=P <- Types2, not cerl_sets:is_element(InfV, Once)], - + Types = Types1 ++ Types0, {meet_types(EqTypes++Types, Ts),subtract_types(Types, Ts)}. infer_eq_type({bif,'=:='}, [#b_var{}=Src,#b_literal{}=Lit], Ts, Ds) -> diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 6efa98de44..a7ffc3f60a 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -222,6 +222,9 @@ coverage(Config) -> booleans(_Config) -> {'EXIT',{{case_clause,_},_}} = (catch do_booleans_1(42)), + ok = do_booleans_2(42, 41), + error = do_booleans_2(42, 42), + AnyAtom = id(atom), true = is_atom(AnyAtom), false = is_boolean(AnyAtom), @@ -250,6 +253,19 @@ do_booleans_1(B) -> no -> no end. +do_booleans_2(A, B) -> + Not = not do_booleans_cmp(A, B), + case Not of + true -> + case Not of + true -> error; + false -> ok + end; + false -> ok + end. + +do_booleans_cmp(A, B) -> A > B. + setelement(_Config) -> T0 = id({a,42}), {a,_} = T0, diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index e67397c6fd..7594514b29 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -188,6 +188,31 @@ is used to keep the table fixated during the entire traversal.</p> </item> </list> + <note> + <p>Even though the access of a single object is always guaranteed to be + <seealso marker="#concurrency">atomic and isolated</seealso>, each traversal + through a table to find the next key is not done with such guarantees. This is often + not a problem, but may cause rare subtle "unexpected" effects if a concurrent + process inserts objects during a traversal. For example, consider one + process doing</p> +<pre> +ets:new(t, [ordered_set, named_table]), +ets:insert(t, {1}), +ets:insert(t, {2}), +ets:insert(t, {3}), +</pre> + <p>A concurrent call to <c>ets:first(t)</c>, done by another + process, may then in rare cases return <c>2</c> even though + <c>2</c> has never existed in the table ordered as the first key. In + the same way, a concurrent call to <c>ets:next(t, 1)</c> may return + <c>3</c> even though <c>3</c> never existed in the table + ordered directly after <c>1</c>.</p> + <p>Effects like this are improbable but possible. The probability will + further be reduced (if not vanish) if table option + <seealso marker="#new_2_write_concurrency"><c>write_concurrency</c></seealso> + is not enabled. This can also only be a potential concern for + <c>ordered_set</c> where the traversal order is defined.</p> + </note> </section> <section> |