diff options
author | Björn Gustavsson <[email protected]> | 2016-10-06 06:01:11 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-10-06 07:10:37 +0200 |
commit | 67808ef46f8f429652ddebb81b0b5c3c603f8655 (patch) | |
tree | c156df806f0b7de28740af748283476ff3aa02b3 /lib/tools/emacs | |
parent | 05be21eb0ad09fcdd63d955ed1d5b50ed34af925 (diff) | |
download | otp-67808ef46f8f429652ddebb81b0b5c3c603f8655.tar.gz otp-67808ef46f8f429652ddebb81b0b5c3c603f8655.tar.bz2 otp-67808ef46f8f429652ddebb81b0b5c3c603f8655.zip |
beam_bsm: Eliminate unsafe optimization
The following code causes a compiler failure:
first_after(Data, Offset) ->
case byte_size(Data) > Offset of
false ->
{First, Rest} = {ok, ok},
ok;
true ->
<<_:Offset/binary, Rest/binary>> = Data,
%% 'Rest' saved in y(0) before the call.
{First, _} = match_first(Data, Rest),
%% When beam_bsm sees the code, the following line
%% which uses y(0) has been optimized away.
{First, Rest} = {First, Rest},
First
end.
match_first(_, <<First:1/binary, Rest/binary>>) ->
{First, Rest}.
Here is the error message from beam_validator:
t: function first_after/2+15:
Internal consistency check failed - please report this bug.
Instruction: {call,2,{f,7}}
Error: {multiple_match_contexts,[{x,1},0]}:
Basically, what happens is that at time of code generation,
the variable 'Rest' is needed after the call to match_first/2
and is therefore saved in y(0). When beam_bsm (a late optimization
pass) sees the code, the use of y(0) following the call
to match_first/2 has been optimized away. beam_bsm therefore
assumes that the delayed sub-binary creation is safe. (Actually,
it is safe, but beam_validator does not realize it.)
The bug was caused by two separate commits:
e199e2471a reduced the number of special cases to handle in BEAM
optimization passed by breaking apart the tail-recursive call
instructions (call_only and call_last) into separate instructions.
Unfortunately, the special handling for tail calls was lost, which
resulted in worse code (i.e. the delayed sub-binary creation
optimization could not be applied).
e1aa422290 tried to compensate, but did so in a way that was not
always safe.
Teaching beam_validator that this kind of code is safe would be
expensive.
Instead, we will undo the damage caused by the two
commits. Re-introduce the special handling of tail-recursive calls in
beam_bsm that was lost in the first commit. (Effectively) revert the
change in the second commit.
ERL-268
Diffstat (limited to 'lib/tools/emacs')
0 files changed, 0 insertions, 0 deletions