diff options
| author | Björn Gustavsson <[email protected]> | 2019-01-31 13:03:28 +0100 | 
|---|---|---|
| committer | Björn Gustavsson <[email protected]> | 2019-01-31 15:42:06 +0100 | 
| commit | 53f85bfa09fa0aea9718c207d4245cb975eb6b08 (patch) | |
| tree | 59c16d1ad174f2373611e3baecbf681f5aa90cc3 /lib/stdlib | |
| parent | 135f98f4481e57f82c03c74a41ebde649af40f04 (diff) | |
| download | otp-53f85bfa09fa0aea9718c207d4245cb975eb6b08.tar.gz otp-53f85bfa09fa0aea9718c207d4245cb975eb6b08.tar.bz2 otp-53f85bfa09fa0aea9718c207d4245cb975eb6b08.zip | |
Fix internal consistency failure caused by beam_except
Fix a bug where the number of live registers in a `bs_get_tail`
instruction was too low.
Consider this example:
    -export([bs_get_tail/2]).
    bs_get_tail(Bin, Config) ->
        bs_get_tail_1(Bin, 0, 0, Config).
    bs_get_tail_1(<<_:32, Rest/binary>>, Z1, Z2, F1) ->
        {Rest,Z1,Z2,F1}.
`beam_validator` would emit the following diagnostics:
    t: function bs_get_tail_1/4+2:
      Internal consistency check failed - please report this bug.
      Instruction: {func_info,{atom,t},{atom,bs_get_tail_1},4}
      Error:       {uninitialized_reg,{x,3}}:
Here is the part of the code that generates the `function_clause`
exception before the optimization:
    {test_heap,6,4}.
    {put_list,{x,3},nil,{x,2}}.
    {put_list,{integer,0},{x,2},{x,2}}.
    {put_list,{integer,0},{x,2},{x,2}}.
    {bs_set_position,{x,1},{x,0}}.
    {bs_get_tail,{x,1},{x,0},3}.     %3 live registers.
    {test_heap,2,3}.
    {put_list,{x,0},{x,2},{x,1}}.
    {move,{atom,function_clause},{x,0}}.
    {line,[{location,"t.erl",8}]}.
    {call_ext_only,2,{extfunc,erlang,error,2}}.
The `bs_get_tail` instruction expects that 3 registers will be live
at this point. `beam_except` rewrites the code like this:
    {bs_set_position,{x,1},{x,0}}.
    {bs_get_tail,{x,1},{x,0},3}.    %Still 3. Too low.
    {move,{integer,0},{x,1}}.
    {move,{integer,0},{x,2}}.
    {jump,{f,3}}.
Now the number of live registers in `bs_get_tail` is too low,
because the `{x,3}` register will become undefined.
This commit adds code to update the number of live registers
in the `bs_get_tail` instruction, producing this code:
    {bs_set_position,{x,1},{x,0}}.
    {bs_get_tail,{x,1},{x,0},4}.    %Adjusted to 4.
    {move,{integer,0},{x,1}}.
    {move,{integer,0},{x,2}}.
    {jump,{f,3}}.
Diffstat (limited to 'lib/stdlib')
0 files changed, 0 insertions, 0 deletions
